【问题标题】:C++ assignment operator, can we replace it with copy?C++赋值运算符,我们可以用copy来代替吗?
【发布时间】:2020-09-11 19:16:05
【问题描述】:

当我阅读时:

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

这里:What's the difference between assignment operator and copy constructor?

如下示例所示:

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

对比:

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

我的问题是,为什么我们需要赋值运算符?我的意思是在这种情况下使用复制构造函数会更有效,同时它执行相同的工作。

有人可以举一个使用赋值运算符的真实例子吗?不能被复制构造函数替换?

【问题讨论】:

  • 我的意思是在这种情况下使用复制构造函数会更有效,同时它执行相同的工作。 -- 无论用户选择什么,您的类都应该工作去做。 有人可以举一个真实世界的例子来说明使用赋值运算符,它不能被复制构造函数替换吗? -- int x = 10; int y = 4; if (something) x = y;
  • 假设您正在使用已经创建的对象池,您需要复制它们
  • 从数组或向量的中间移除一个元素?如果没有赋值,你将如何“转移”其他元素?
  • @PaulMcKenzie 为什么不int y = 4; int x = (something) ? y : 10;
  • 为什么不步行 25 英里而不是开车呢?这基本上就是它正在沸腾的内容。当可以完成简单的重新分配时,以这样的方式编写代码是没有意义的。

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


【解决方案1】:

当你想在一个值已经被构造之后改变它时,你需要赋值。例如:

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

这个列表真的可以几乎无穷无尽。但在您的示例中,确实可以简单地避免使用赋值。

【讨论】:

    【解决方案2】:

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

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

    复制构造函数在对象生命周期内只被调用一次,如果它在其声明期间被初始化。每隔一次你给它分配其他对象,赋值构造函数就会被调用。

    【讨论】:

    • 你的答案是错误的,“但是在赋值构造函数中,只有一个对象中的字段值被复制到另一个对象。调用赋值构造函数时没有分配新的内存”
    • @smith_brown -- 对于普通可复制类型,不分配新内存,编译器执行高效复制(可能使用memcpy)操作。
    • 我建议使用更标准的语言。构造函数不分配对象存储(它们需要已经分配的存储)。此外,我们在 C++ 中没有任何 赋值构造函数
    【解决方案3】:

    是的,有一个著名的,赋值运算符不能被复制构造函数代替:

     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 限定赋值运算符和预递增和预递减迭代器运算符是标准库提供的产生悬空引用的最佳机会。

    【讨论】:

      【解决方案4】:

      理论上,任何复制赋值都可以通过调用析构函数来替换,然后调用复制构造函数,因为构造函数不负责为新实例分配内存。您实际上可以调用构造函数,而无需使用placement new 运算符分配任何内存。

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

      复制赋值和构造函数的最大区别在于,在赋值中你可以依赖内存已经初始化的事实。在最好的情况下,这种预初始化不会提供任何好处,并且复制构造函数与复制分配一样高效。在其他情况下,复制赋值会从中受益,并且比构造函数更高效。

      您可以将调用成本添加到析构函数中,并且复制构造函数变得比赋值更不有趣。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-16
        • 2021-10-22
        • 2019-01-06
        • 1970-01-01
        • 1970-01-01
        • 2010-09-18
        • 2021-11-16
        • 1970-01-01
        相关资源
        最近更新 更多