我读了C++ primer第5版。当我们在使用复制和交换的赋值操作符中使用非参考参数时,我发现它是可以的,但在其他赋值操作符中,我们总是使用参考参数并在销毁左操作数之前复制右手操作数,以确保如果一个对象被分配给自己,赋值操作符就可以正常工作为什么不在将在函数体中稍后复制的赋值运算符中使用非引用参数,以便我们不需要复制函数体中的右侧操作数?为什么要在C++中通过引用传递赋值运算符的参数?
回答
复制赋值操作符通常应该按值(不是引用)采用它们的参数,以便使用by-value参数作为副本进行复制和交换。
如果你没有做(只是)复制和交换,那么也许你的副本赋值运算符应该通过引用采用它的参数。至于你为什么不做复制和交换:可能是因为该类型的某些特定的优化。考虑一个简单可复制类型的std::array
(为避免谈论异常安全性的麻烦,我们可以省略一点)。最有效的可能的任务是直接复制字节:不需要对象的临时副本,并且您肯定不需要交换。因此,在实践中,您需要通过参考采用参数,编写std::copy
,并期望编译器以最佳方式执行此操作。
复制赋值运算符中的特殊外壳自赋值有时会在教科书中看到,即使使用了copy-and-swap,但在C++ 03中通常是一个坏主意。虽然它优化了自我分配的情况,但通过引用参数可以优化临时分配的情况。在C++ 11中,它不太明显不好,因为临时分配的情况可以由移动赋值运算符而不是复制赋值运算符来处理。但它可能仍然没有必要。在实际代码中,自分配很少见,因此甚至可以发现,在极少数情况下,常见情况下的指针比较运算结果高于。
我还没有阅读第五版的“C++ Primer”,并且你选择不显示你询问的代码,所以我不能评论它给出赋值操作符的具体情况(复制分配或以其他方式),通过引用参数。
对不起,但总的来说,我认为这是统计上更可能你感到困惑比书;-)你说:
...在使用复制和交换赋值运算符,但在其他赋值运算符
好了,“其他赋值运算符”是赋值运算符是不使用复制和交换?
我们一直使用的参考参数和销毁 左侧操作数
之前复制右手操作如果复制右侧操作数,那么你是做复制和交换。或者至少你非常接近它,因为做了一个副本,除了交换以外,没有什么意义可以使副本进入左侧。无论哪种方式,如果一个函数的第一件事是复制一个引用参数,那么它应该已经通过值获取参数。
以确保赋值运算符正常工作,如果一个对象被分配到自身
如果您确保自分配技术工作正确方法是始终复制右手操作数,那么你应该按值来取参数。没有其他需要。但是,还有其他技术可以确保自我分配工作。有可能其中之一发生在你没有显示的代码中。
非常感谢你的回答,我之所以没有显示代码是因为我有点懒惰:(我认为我可以清楚地表达出来,但是...我很抱歉,无论如何,我已经得到了我的回答,谢谢 – Sherwin
主要原因是效率。对于一个小类/结构体来说,它可能并不重要,但如果它是一个大型复杂类,那是另一回事。如果您按值传递,则将调用可能较大且复杂的复制操作。这可能需要大量的内存分配。
真正的答案是有时候没关系。通常它确实是很重要,所以最好的方法就是始终使用参考。
- 1. 为什么在C++中通过引用传递的参数不需要解引用运算符?
- 2. 为什么在C中通过引用传递字符数组?
- 3. 为什么参数可以通过赋值运算符在对象初始化时传递给构造函数?
- 4. Visual C++ 2012:为什么priority_queue需要重载赋值运算符?
- 5. 为什么要在PHP中通过引用传递原始类型参数?
- 6. C#引用赋值运算符?
- 7. PHP中的引用赋值运算符,=&
- 8. 为什么Perl允许通过引用传递参数?
- 9. 通过引用传递一个对象重载运算符 - C++
- 10. 为什么JavaScript通过引用传递?
- 11. 为什么C++将赋值(=)视为重载运算符?
- 12. 清除std :: vector需要赋值运算符。为什么?
- 13. 为什么在通过参数传递值时会得到零?
- 14. 在C++中通过引用传递函数参数的问题
- 15. 函数参数C++中的赋值运算符
- 16. 为什么调用赋值运算符触发销毁函数?
- 17. 通过引用传递串并通过在C函数参数++更新其值
- 18. 为什么C没有逻辑赋值运算符?
- 19. c赋值运算符=
- 20. C++“| =”赋值运算符
- 21. 什么是| =赋值运算符?
- 22. 默认赋值运算符参数
- 23. 为什么在VB.NET中赋值运算符不可重载?
- 24. 通过引用传递const值的C++
- 25. 在C++中通过引用和值传递字符串
- 26. C++:使用&运算符通过引用
- 27. 为什么赋值运算符返回一个值而不是引用?
- 28. 通过引用传递的ANT参数
- 29. 通过引用的CreateInstance传递参数
- 30. 通过引用参数传递跟踪递归算法
请显示您正在谈论的代码。 – greatwolf