【问题标题】:Behaviour of explicit copy constructor显式复制构造函数的行为
【发布时间】:2020-08-18 18:29:38
【问题描述】:

我有以下代码:

#include <iostream>

struct A {
  A(int x=1, int y=1) : x(x), y(y) { }
  A(const A& other) : x(other.x), y(other.y) { }

  operator bool() const { return !x && !y; }

  friend std::ostream& operator<<(std::ostream& os, const A& a) {
    os << a.x << "," << a.y << "\n";
    return os;
  }

  int x;
  int y;
};

int main(int argc, char const *argv[]) {
  A const A10x10(10, 10);
  A a;
  std::cout << a;
  A aa = A10x10;
  std::cout << aa;
  return 0;
}

以上打印:

1,1
10,10

当我将复制构造函数更改为显式(即explicit A(const A&amp; other);)时,我得到:

1,1
0,1

我在(显式)复制构造函数中放置了一个打印语句,实际上它没有被调用。为什么会这样? explicit 有什么不同?

我使用的是 C++17,用 Clang10 编译。

【问题讨论】:

  • 这是一个错字A::A() : x(x), y(y) {}(缺少参数)吗?如果没有,你有 UB。
  • 你能提供一个minimal reproducible example吗?如果你明确复制构造函数,你的代码应该编译失败......不仅仅是没有被调用或做其他事情。
  • 此代码不是compile。请发minimal reproducible example
  • 实际上,我看到的恰恰相反。 10,10 隐式时,0,1 显式时。
  • A aa = A::A10x10;这一行更改(或添加aaa版本)为bool temp = A::A10x10; A aa = temp;现在你明白了吗?

标签: c++ constructor c++17 copy-constructor


【解决方案1】:

这个:

A aa = A10x10;

执行复制初始化。复制初始化通过将对象转换为正在初始化的对象的类型来工作。但是,复制初始化是通过隐式转换来实现的。而隐式转换不能调用explicit构造函数。

即使是复制构造函数。

现在,您可能会认为您会收到编译错误。但你没有。为什么?因为A 可以通过用户定义的转换隐式转换为bool。而bool 可以通过标准转换为int。而A 实际上可以从int 类型的单个值构造。虽然隐式转换只允许进行一次用户定义的转换,但它确实允许进行一次用户定义的转换,然后进行标准转换。

所以这就是发生的事情。这就是为什么当复制构造函数为explicitaa 中的第一个值为0。

一般来说,总是制作operator boolexplicit从不创建复制构造函数explicit

【讨论】:

  • 感谢您的回答。它非常清楚。如果您不介意,我有一个后续问题。说,我也超载了operator int,会选择那个而不是operator bool吗?如果是这样,是因为 int 转换比 bool 转换更接近 A(int, int) 构造函数的类型吗?
猜你喜欢
  • 2012-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-19
  • 2015-06-10
  • 2012-02-28
  • 2023-03-22
相关资源
最近更新 更多