C++ 复制构造构造和赋值问题 [英] C++ copy-construct construct-and-assign question

查看:31
本文介绍了C++ 复制构造构造和赋值问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里摘录自C++ Gotchas"一书第 56 条:

<块引用>

经常看到一个简单的写入的 Y 对象的初始化三种不同方式中的任何一种,好像它们是等价的.

Y a( 1066 );Y b = Y(1066);Yc = 1066;

<块引用>

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

b 和 c 的初始化是更复杂.其实他们太复杂的.这两个都是副本初始化.在这种情况下b 的初始化,我们请求创建匿名临时Y 类型,用值初始化1066.然后我们使用这个匿名临时作为参数复制要初始化的类 Y 的构造函数湾最后,我们调用析构函数匿名临时工.

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

有谁知道语言标准是否发生了变化,或者这只是编译器的优化功能?我使用的是 Visual Studio 2008.

代码示例:

#include 类小部件{std::string 名称;民众://构造函数小部件(std::string n){ name=n;std::cout <<构建小部件" <<这个->名字<<std::endl;}//复制构造函数小部件 (const Widget& rhs) { std::cout <<从<<复制构建Widgetrhs.name <<std::endl;}//赋值运算符小工具&operator=(const Widget& rhs) { std::cout <<从"分配小部件<<rhs.name <<到" <<这个->名字<<std::endl;返回 *this;}};int main(void){//构造小部件 a("a");//复制构造小部件 b(a);//构造并赋值小部件 c("c");c = 一个;//复制构造!小部件 d = a;//构造!小部件 e = "e";//构造并赋值小部件 f = 小部件(f");返回0;}

输出:

构造Widget a从一个复制构建 Widget构建 Widget c将 Widget 从 a 分配到 c从一个复制构建 Widget构建小部件 e构建 Widget f从 f 复制构造 Widget

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

解决方案

语法

X a = b;

a 和 b 是 X 类型的地方总是意味着复制构造.任何变体,例如:

X a = X();

被使用过,没有进行赋值,也从未使用过.构造和分配将类似于:

X a;a = X();

Here is an extract from item 56 of the book "C++ Gotchas":

It's not uncommon to see a simple initialization of a Y object written any of three different ways, as if they were equivalent.

Y a( 1066 ); 
Y b = Y(1066);
Y c = 1066;

In point of fact, all three of these initializations will probably result in the same object code being generated, but they're not equivalent. The initialization of a is known as a direct initialization, and it does precisely what one might expect. The initialization is accomplished through a direct invocation of Y::Y(int).

The initializations of b and c are more complex. In fact, they're too complex. These are both copy initializations. In the case of the initialization of b, we're requesting the creation of an anonymous temporary of type Y, initialized with the value 1066. We then use this anonymous temporary as a parameter to the copy constructor for class Y to initialize b. Finally, we call the destructor for the anonymous temporary.

To test this, I did a simple class with a data member (program attached at the end) and the results were surprising. It seems that for the case of c, the object was constructed by the copy constructor rather than as suggested in the book.

Does anybody know if the language standard has changed or is this simply an optimisation feature of the compiler? I was using Visual Studio 2008.

Code sample:

#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;
}

Output:

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

I was most surprised by the results of constructing d and e. To be precise, I was expecting an empty object to be created, and then an object to be created and assigned to the empty object. In practice, the objects were created by the copy constructor.

解决方案

The syntax

X a = b;

where a and b are of type X has always meant copy construction. Whatever variants, such as:

X a = X();

are used, there is no assignment going on, and never has been. Construct and assign would be something like:

X a;
a = X();

这篇关于C++ 复制构造构造和赋值问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆