提问人: 提问时间:5/25/2020 更新时间:5/25/2020 访问量:638
C++赋值运算符,我们可以用copy代替吗?
C++ assignment operator, can we replace it with copy?
问:
当我阅读时:
赋值运算符和复制符有什么区别 构造 函数?
显示了以下示例:
A aa;
A a = aa; //copy constructor
与:
A aa;
A a;
a = aa; // assignment operator
我的问题是,为什么我们需要赋值运算符?我的意思是,在这种情况下,使用复制构造函数会更有效,同时它执行相同的工作。
有人可以举一个实际的例子来说明使用赋值运算符,其中不能被复制构造函数替换吗?
答:
如果要在构造值后更改值,则需要赋值。例如:
- 更改已存储在
std::map
- 更改
std::vector
- 在循环外更改变量的值
- 更改作为指针或引用提供的输出参数的值
- ...
这个名单真的可以几乎无休止地继续下去。但是在你的例子中,确实可以简单地避免使用赋值。
复制构造函数仅调用一次 - 在对象初始化时。调用 copy 构造函数时,它会为变量分配一个新的内存块,然后将其分配给另一个对象。
但在赋值构造函数中,只有一个对象中的字段值被复制到另一个对象,并且在调用赋值构造函数时分配相同的内存。这是复制构造函数和赋值构造函数之间的主要区别。复制构造函数为两个对象分配单独的内存,即新创建的目标对象和源对象。赋值运算符将相同的内存位置分配给新创建的目标对象和源对象。
复制构造函数在对象生存期中仅调用一次,前提是它在声明期间初始化。每隔一段时间,您将其他对象分配给它,将调用赋值构造函数。
评论
memcpy
是的,有一个著名的,其中赋值运算符不能被复制构造函数替换:
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.
}
非引用限定赋值运算符以及预递增和预递减迭代器运算符是标准库提供的生成悬空引用的最佳机会。
从理论上讲,任何复制分配都可以替换为对析构函数的调用,然后调用复制构造函数,因为构造函数不负责为新实例分配内存。实际上,您可以使用 placement new 运算符调用构造函数,而无需分配任何内存。
但是,复制赋值相对于复制构造函数仍然很有意义,并且您认为复制构造函数性能更高的假设是错误的。
复制赋值和构造函数之间的最大区别在于,在赋值中,您可以依赖内存已经初始化的事实。在最好的情况下,这种预初始化不会提供任何好处,并且复制构造函数的性能与复制分配一样。在其他情况下,复制赋值从中受益,并且比构造函数性能更高。
你可以将调用的成本添加到析构函数中,复制构造函数在赋值中变得不那么有趣。
评论
int x = 10; int y = 4; if (something) x = y;
int y = 4; int x = (something) ? y : 10;