C ++赋值运算符,我们可以将其替换为副本吗?

时间:2020-05-25 07:17:21

标签: c++ operators copy-constructor assignment-operator

当我阅读时:

赋值运算符和副本有什么区别 构造函数?

此处:What's the difference between assignment operator and copy constructor?

显示了以下示例:

A aa;
A a = aa;  //copy constructor

vs:

A aa;
A a;
a = aa;  // assignment operator

我的问题是,为什么我们完全需要赋值运算符?我的意思是,在这种情况下,使用拷贝构造函数执行相同的工作将更加有效。

有人可以举一个使用赋值运算符的真实示例,而该赋值运算符不能被副本构造函数取代吗?

4 个答案:

答案 0 :(得分:2)

在构造一个值后要更改它时,需要分配。例如:

  • 更改已存储在std::map中的值
  • 更改std::vector内的第n个值
  • 在循环外更改变量的值
  • 更改作为指针或引用提供的输出参数的值
  • ...

该列表几乎可以无休止地持续下去。但是在您的示例中,确实可以避免使用赋值。

答案 1 :(得分:0)

复制构造函数仅在对象初始化时被调用一次。调用copy构造函数时,它将为该变量分配一个新的内存块,然后为其分配另一个对象。

但是在分配构造器中,只有一个对象中的字段值被复制到另一对象,并且在调用分配构造器时分配了相同的内存。那是复制构造函数和赋值构造函数之间的主要区别。复制构造函数为两个对象(即新创建的目标对象和源对象)分配单独的内存。分配运算符将相同的内存位置分配给新创建的目标对象以及源对象。

复制构造函数在对象生命周期中仅被调用一次,这是在其声明期间初始化的。每隔一次向其分配其他对象,就会调用分配构造函数。

答案 2 :(得分:0)

是的,有一个著名的例子,赋值运算符不能被拷贝构造函数代替:

 std::vector <int> f();
 void g(){
     decltype(auto) v = f() = f();
     v.push_back(10); //boum undefined behaviour.
        //without the non ref qualified copy assignment operator you
        //could not have the pleasure to have undiscoverable UB in your code.
     }

非ref合格的赋值运算符以及预递增和递减迭代器运算符是标准库提供的最好的机会来产生悬挂的引用。

答案 3 :(得分:0)

从理论上讲,任何复制分配都可以由对析构函数的调用替换为对复制构造函数的调用,因为该构造函数不负责为新实例分配内存。实际上,您可以使用placement new运算符调用构造函数而无需分配任何内存。

但是,复制分配对于复制构造函数仍然很有趣,并且您认为复制构造函数性能更高的假设是错误的。

副本分配与构造函数之间的最大区别在于,在分配中,您可以依靠内存已经初始化的事实。最好的情况是,这种预初始化不会带来任何好处,并且复制构造函数的性能与复制分配的性能相同。在其他情况下,副本分配会从中受益,并且比构造函数更有效。

然后您可以将调用的成本添加到析构函数中,而复制构造函数在分配时变得不再那么有趣了。

相关问题