i read the C++ primer 5th. i saw that it is ok when we use non-reference parameters in assignment operators that use copy and swap,but in the other assignment operators we always use reference parameters and copy the right-hand operand before destroying left-hand operand to make sure the assignment operators work correctly if an object is assigned to itself. why not use non-reference parameter in the assignment operators that will copy in the function body later so that we need not copy the right-hand operand in the function body?
2 回答
复制赋值运算符通常应该按值(而不是引用)获取其参数,以便使用按值参数作为副本进行复制和交换。
如果您不(只是)进行复制和交换,那么您的复制赋值运算符可能应该通过引用获取其参数。至于为什么不进行复制和交换:可能是因为对类型进行了一些特定的优化。例如std::array
,考虑一个可简单复制的类型(为了省去我们谈论异常安全的麻烦)。最有效的可能分配是直接复制字节:您不想要对象的临时副本,当然也不想要交换。因此,在实践中,您会通过引用、编写参数来获取参数std::copy
,并期望编译器能够以最佳方式执行此操作。
复制赋值运算符中的特殊情况自赋值有时会在教科书中看到,即使是复制和交换,但在 C++03 中通常是一个坏主意。尽管它优化了自赋值的情况,但 by-reference 参数对临时赋值的情况进行了优化。在 C++11 中,这显然不太糟糕,因为临时赋值的情况可以通过移动赋值运算符而不是复制赋值运算符来处理。但这可能仍然没有必要。自赋值在实际代码中非常少见,因此甚至可以证明,常见情况下的指针比较加起来比罕见情况下的副本要多。
我还没有阅读“C++ Primer”的第 5 版,并且您选择不显示您要询问的代码,因此我无法评论其中给出赋值运算符(复制赋值或否则)通过引用获取参数。
抱歉,但总的来说,我认为从统计学上讲,您比这本书更容易感到困惑;-)您说:
...在使用复制和交换的赋值运算符中,但在其他赋值运算符中
好的,那么“其他赋值运算符”是不使用复制和交换的赋值运算符吗?
我们总是使用引用参数并在销毁左侧操作数之前复制右侧操作数
如果您复制右手操作数,那么您就是在进行复制和交换。或者至少你非常接近它,因为制作了一个副本,使用除了交换之外的任何东西将副本放入左侧几乎没有意义。无论哪种方式,如果一个函数做的第一件事是复制一个引用参数,那么它应该按值获取参数。
如果将对象分配给自身,则确保赋值运算符正常工作
如果您确保自赋值正常工作的技术是始终复制右侧操作数,那么您应该按值获取参数。不需要其他任何东西。但是,还有其他技术可以确保自分配工作正常。其中一个可能发生在您未显示的代码中。
主要原因是效率。对于一个小的类/结构,这可能无关紧要,但如果它是一个大的复杂类,那就另当别论了。如果您按值传递,您将调用一个潜在的大而复杂的复制操作。这可能需要大量的内存分配。
真正的答案是,有时这并不重要。通常它确实很重要,因此最好的方法是始终使用参考。