C++ copy-construct构造和分配问题

And*_*ndy 7 c++ constructor copy-constructor assignment-operator

以下是"C++ Gotchas"一书第56条的摘录:

通过三种不同方式编写Y对象的简单初始化并不罕见,就像它们是等效的一样.

Y a( 1066 ); 
Y b = Y(1066);
Y c = 1066;
Run Code Online (Sandbox Code Playgroud)

事实上,所有这三个初始化可能会导致生成相同的目标代码,但它们并不相同.a的初始化称为直接初始化,它完全符合人们的期望.初始化是通过直接调用Y :: Y(int)完成的.

b和c的初始化更复杂.事实上,它们太复杂了.这些都是复制初始化.在初始化b的情况下,我们要求创建一个Y类型的匿名临时值,用值1066初始化.然后我们使用这个匿名临时值作为类Y的拷贝构造函数的参数来初始化b.最后,我们将析构函数称为匿名临时.

为了测试这个,我做了一个带有数据成员的简单类(最后附加了程序),结果令人惊讶.似乎对于c的情况,对象是由复制构造函数构造的,而不是书中所建议的.

有人知道语言标准是否已经改变,或者这只是编译器的优化功能?我使用的是Visual Studio 2008.

代码示例:

#include <iostream>

class Widget
{
    std::string name;
public:
    // Constructor
    Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
    // Copy constructor
    Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
    // Assignment operator
    Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};

int main(void)
{
    // construct
    Widget a("a");
    // copy construct
    Widget b(a);
    // construct and assign
    Widget c("c"); 
    c = a;
    // copy construct!
    Widget d = a;
    // construct!
    Widget e = "e";
    // construct and assign
    Widget f = Widget("f");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Constructing Widget a

Copy constructing Widget from a

Constructing Widget c
Assigning Widget from a to c

Copy constructing Widget from a

Constructing Widget e

Constructing Widget f
Copy constructing Widget from f
Run Code Online (Sandbox Code Playgroud)

我对构建d和e的结果感到非常惊讶.确切地说,我期望创建一个空对象,然后创建一个对象并将其分配给空对象.实际上,对象是由复制构造函数创建的.

小智 16

语法

X a = b;
Run Code Online (Sandbox Code Playgroud)

其中a和b是X型,总是意味着复制结构.无论变体如何,例如:

X a = X();
Run Code Online (Sandbox Code Playgroud)

使用,没有任务,从来没有.构造和分配将是这样的:

X a;
a = X();
Run Code Online (Sandbox Code Playgroud)


sbi*_*sbi 6

允许编译器优化案例bc与之相同a.此外,编译器无论如何都可以完全消除复制构造和赋值操作符调用,因此无论你看到什么,不一定与不同的编译器甚至编译器设置相同.

  • @Andy,这本书没有100%正确.但它不是100%完成.如果您想要100%完成,您需要参考标准.具体来说,它(或您引用的部分)并未解释如果从上述临时复制完成复制,则允许编译器优化副本. (4认同)
  • 不,你不应该.使用更清楚的,不要担心那些微小的优化. (3认同)