即使从未调用过副本 CTOR 是不是也需要?

Posted

技术标签:

【中文标题】即使从未调用过副本 CTOR 是不是也需要?【英文标题】:Is the copy CTOR required even if never called?即使从未调用过副本 CTOR 是否也需要? 【发布时间】:2011-09-12 16:02:12 【问题描述】:

考虑以下几点:

class X 
public:
    X(int i)  cout << "X(int i)" << endl; 
    X(const X& x)  cout << "X(const X& x)" << endl; 
;

void main() 
    X x1(1);
    X x2 = X(1);
    X x3 = (X)1;

运行此代码会产生以下输出:

X(int i)
X(int i)
X(int i)

我认为以上三个语句都是等效的,因为永远不会调用副本 CTOR。但是,将X 的副本 CTOR 更改为私有:

class X 
public:
    X(int i)  cout << "X(int i)" << endl; 
private:
    X(const X& x)  cout << "X(const X& x)" << endl; 
;

将无法编译(在 Visual Studio 2010 中)并出现此错误:

cannot access private member declared in class 'X'

所以看起来复制 CTOR 以某种方式涉及,虽然我不太明白如何。

谢谢

【问题讨论】:

【参考方案1】:

Ist 对象使用您所知道的参数化构造函数,而所有其他对象都使用复制构造函数。即为什么当你让它发生私人访问冲突时。其他两个对象正在使用复制构造函数。

这些是使用复制构造函数的方式。

【讨论】:

【参考方案2】:
X x1(1);
X x2 = X(1);
X x3 = (X)1;

原因是所有这些都不完全等价。

第一个是直接初始化,第二个和第三个是复制初始化。复制初始化,复制构造函数必须是公共的,否则编译器会报错。

现在的问题是,如果 2nd 和 3rd 要求 copy-ctor 是公开的,那么为什么会出现以下输出:

X(int i)
X(int i)
X(int i)

这肯定说明 copy-ctor 永远不会被调用,这是真的。编译器只是忽略了对 copy-ctor 的调用。根据 §8.5/14,在这种情况下,允许编译器消除调用复制构造函数的需要。这就是为什么你看不到 copy-ctor 被调用的原因。

有点内部:在第 2 和第 3 种情况下,首先通过调用 X(int i) 创建一个临时文件,然后这个临时文件应该被传递给 copy-ctor 以复制初始化被声明的对象。但是编译器优化了这一步,省略了对 copy-ctor 的调用。

【讨论】:

如果您添加一些关于第二行和第三行的实际差异以及在什么情况下的信息会很有趣(在这种情况下根据 8.5/14...) 回答【参考方案3】:

    这个:

    X x3 = (X)1; 是从int 转换为X 类型的对象的c 风格

    本次抄袭:

    X x2 = X(1);

已优化,但编译器仍需要访问复制构造函数。

【讨论】:

【参考方案4】:

X x2 = ... 调用复制构造函数(即使编译器稍后对其进行优化)。因此,它必须仍然可以访问。

【讨论】:

以上是关于即使从未调用过副本 CTOR 是不是也需要?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 中用于更新的版本控制

要求 r 函数在全局环境中使用对象而不是对象的副本

MongoDB副本集

kafkakafka topic某些分区 副本落后leader太多

为啥在初始化列表中没有创建额外副本的情况下分配数据?

递减 std::vector::begin 是不是未定义,即使从未使用过?