C++ 为什么在这种情况下不调用复制构造函数?
以下是小代码片段:C++ 为什么在这种情况下不调用复制构造函数?,c++,constructor,copy-constructor,C++,Constructor,Copy Constructor,以下是小代码片段: class A { public: A(int value) : value_(value) { cout <<"Regular constructor" <<endl; } A(const A& other) : value_(other.value_) { cout <<"Copy constructor" <<endl; }
class A
{
public:
A(int value) : value_(value)
{
cout <<"Regular constructor" <<endl;
}
A(const A& other) : value_(other.value_)
{
cout <<"Copy constructor" <<endl;
}
private:
int value_;
};
int main()
{
A a = A(5);
}
A类
{
公众:
A(int值):值(value)
{
cout来自另一条评论:“因此默认情况下我不应该依赖它(因为它可能依赖于编译器)”
不,实际上它并不依赖于编译器。任何一个有价值的编译器都不会浪费时间构造一个a,然后复制它
在该标准中,它明确指出,T=x;
等同于说T(x);
(§12.8.15,第211页)用T(T(x))
这样做显然是多余的,因此它删除了内部T
要获得所需的行为,您需要强制编译器默认构造第一个:
A a;
// A is now a fully constructed object,
// so it can't call constructors again:
a = A(5);
这里,您可以从临时代码< >(5)< /C>中初始化<代码> A<代码>代码。允许执行跳过调用复制构造函数的C++标准12.2/2。
A a = A(5);
这条线相当于
A a(5);
尽管其函数样式外观,第一行仅用参数5构造<代码> A/COD>。没有复制或临时性。从C++标准,第121.11:
函数表示法类型转换(5.2.3)可用于创建其类型的新对象
语法看起来像是构造函数的显式调用。-结束说明]
我在研究这个问题是为了回答另一个被当作傻瓜的问题,所以为了不让工作白白浪费,我现在回答这个问题
形式为A A=A(5)
的语句称为变量A
的复制初始化。C++11标准8.5/16规定:
使用初始值设定项表达式调用所选函数,如下所示
它的参数;如果函数是构造函数,则调用初始化
目标类型的cv非限定版本的临时版本
temporary是一个prvalue。调用的结果(即临时
对于构造函数的情况),则根据
根据上述规则,对象是
复制初始化。在某些情况下,允许实现
要消除此直接初始化中固有的复制,请执行以下操作:
将中间结果直接构造到正在生成的对象中
已初始化;请参见12.2、12.8
这意味着编译器会查找适当的构造函数来处理A(5)
,创建一个临时文件并将该临时文件复制到A
中。但是在什么情况下可以消除复制
让我们看看12.8/31是怎么说的:
当满足某些条件时,允许忽略实现
类对象的复制/移动构造,即使复制/移动
对象的构造函数和/或析构函数有副作用。In
在这种情况下,实现将处理
省略了复制/移动操作,仅作为两种不同的引用方式
对于同一对象,该对象的销毁发生在
后来这两个物体会被摧毁
没有优化。这省略了复制/移动操作,
在下列情况下,允许复制省略
(可组合使用以消除多个副本):
[……]
- 复制/移动未绑定到引用(12.2)的临时类对象时
对于具有相同cv类型的类对象,可以执行复制/移动操作
通过将临时对象直接构造到省略的复制/移动的目标中来省略
记住所有这些,下面是表达式aa=A(5)
的用法:
编译器会看到带有副本初始化的声明
选择A(int)
构造函数初始化临时对象
由于临时对象未绑定到引用,并且它与复制初始化表达式中的目标类型具有相同的类型a
,因此允许编译器直接将对象构造到a
,从而省略临时对象
谢谢GMan,我无论如何都不使用这个语法。只是要记住一些东西。哦,刚刚在MSDN上找到:C++标准允许复制构造函数的删除(参见第12.8节。复制类对象,第15段)。谢谢,我现在看到了。在答案中引用有点多,所以我将按数字引用。这取决于编译器。标准允许不同的行为,请参见我的答案。它是优化的,避免了构造+复制。我发现这是一个很好的假设,没有用户会根据参数构造,这与复制构造的方式不同。请参见:在g++中,您可以使用选项-fno elide constructors禁用此优化。我认为这不正确。12.2.2中的示例涉及在构造本地对象之前将临时对象传递给函数。不,它不是等效的。一个是复制初始化,另一个是直接初始化。