C++赋值运算符,我们可以用copy代替吗?

C++ assignment operator, can we replace it with copy?

提问人: 提问时间:5/25/2020 更新时间:5/25/2020 访问量:638

问:

当我阅读时:

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

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

显示了以下示例:

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

与:

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

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

有人可以举一个实际的例子来说明使用赋值运算符,其中不能被复制构造函数替换吗?

C++ 运算 复制构造函数 赋值运算符

评论

1赞 PaulMcKenzie 5/25/2020
我的意思是,在这种情况下,使用复制构造函数会更有效,同时它执行相同的工作。-- 无论用户选择做什么,您的类都应该工作。 有人可以举一个真实世界的例子来说明赋值运算符的使用,其中不能被复制构造函数替换? -- int x = 10; int y = 4; if (something) x = y;
0赞 yaodav 5/25/2020
假设您正在使用 AllReady 创建的对象池,您需要复制 theam
0赞 Daniel Langr 5/25/2020
从数组或向量的中间删除元素?如何在没有赋值的情况下“转移”其他元素?
0赞 Jasper Kent 5/25/2020
@PaulMcKenzie为什么不呢?int y = 4; int x = (something) ? y : 10;
0赞 PaulMcKenzie 5/25/2020
为什么不步行 25 英里而不是开车呢?这基本上就是归结为什么。在这样的情况下编写代码是没有意义的,因为可以进行简单的重新赋值。

答:

2赞 Jan Schultke 5/25/2020 #1

如果要在构造值后更改值,则需要赋值。例如:

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

这个名单真的可以几乎无休止地继续下去。但是在你的例子中,确实可以简单地避免使用赋值。

0赞 Abhishek Bhagate 5/25/2020 #2

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

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

复制构造函数在对象生存期中仅调用一次,前提是它在声明期间初始化。每隔一段时间,您将其他对象分配给它,将调用赋值构造函数。

评论

0赞 5/25/2020
你的回答是错误的,“但是在赋值构造函数中,只有一个对象中的字段值被复制到另一个对象。调用赋值构造函数时未分配新内存”
1赞 PaulMcKenzie 5/25/2020
@smith_brown -- 对于简单可复制的类型,不会分配新的内存,编译器会执行有效的复制(可能使用 )操作。memcpy
3赞 Daniel Langr 5/25/2020
我建议使用一些更标准的语言。构造函数不分配对象存储(它们需要已经分配的存储)。此外,我们在 C++ 中没有任何赋值构造函数
0赞 Oliv 5/25/2020 #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.
     }

非引用限定赋值运算符以及预递增和预递减迭代器运算符是标准库提供的生成悬空引用的最佳机会。

0赞 Nicolas Dusart 5/25/2020 #4

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

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

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

你可以将调用的成本添加到析构函数中,复制构造函数在赋值中变得不那么有趣。