c++ - 将赋值运算符标记为左值是否会提高安全性?

标签 c++ c++11 operator-overloading assignment-operator

如果T是赋值运算符默认签名的类类型,那么我们可以这样写:

T const &ref = ( T{} = something ); 

创建一个悬空引用。但是,带有签名:

T &operator=(T t) &

上面带有悬空引用的代码将无法编译。这将防止某些我们返回指定临时对象的左值的情况——不希望出现的情况,因为它们会导致悬空引用。

有什么理由不这样做吗?我们会禁用赋值运算符的任何有效用例吗?

我认为同样的评论也适用于复合赋值运算符,+= 等。更现实的情况可能是:

std::string const &s = std::string("Hello, ") += "world!";

在运行时 UB 之前,拼写错误不会被注意到。

最佳答案

根据我的经验,在极少数情况下您确实想要分配给右值,写作

template<class T>
std::remove_reference_t<T>& as_lvalue(T&&t){return t;}

并用 as_lvalue( tmp() ) = foo 代替 tmp()=foo 并不是一个巨大的障碍。这确实意味着 确实 分配给右值的偶尔的代码现在要中断了;我个人怀疑大多数此类情况实际上是未发现的错误。


在法兰克福的 C++11 标准化期间(2009/07)考虑将 std 中的每个类型限制为 operator= 上的左值限制。 minutes中记录的解析推理是:

N2819, "N2819 Ref-Qualifiers for assignment operators of the Standard Library" was initially considered by the LWG. This proposal sought to change 350 copy-assignment operators in the C++ standard library to prevent assignment operations in which the left operand is an rvalue. Due to the large number of changes required, the proposal was sent to EWG, with the request that the default behavior for implicit copy-assignment operators be reconsidered, so that assignment to an rvalue is not permitted. The EWG resolved to maintain the status quo, because of concerns about backwards compatibility.

我读到的意思是“350 次更改?更改语言怎么样?”。 EWG 说“不,语言更改可能会破坏兼容性”。并且该提案可能半途而废。

2009 年,C++11(当时的 C++0x)已经落后于计划。由于该提议涉及对库进行 300 次更改(理论上)可能会导致回归。 session 记录中没有提到其他原因。它因为不值得回归的痛苦而被拒绝(甚至检查回归的频率!)是可以理解的。所以我不会仅仅因为 C++ 在 std 中拒绝了它就假定对这个想法有偏见。

关于c++ - 将赋值运算符标记为左值是否会提高安全性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28598468/

相关文章:

c++ - 决策搜索树中的 LINK 错误 2019 和 1120

c++ - 对结构列表进行排序

c++ - 我正在尝试使用 ifstream 将这个 C 函数的等效代码转换为 C++

c++ - 如何有效地使用 std::threads 来减少运行时间

c++ - 元组中返回的对象的 std::tie 和生命周期

c++ - Typedef数组指针参数的C++ ostream重载

c++ - 为什么我的 MFC 应用程序不能完全退出?

c++ - std::conditional_variable::notify_all 不唤醒所有线程

c++ - 我应该使用哪种 C++ 运算符重载变体?而且,为什么?

c# - 在 .NET 中,在实现隐式转换运算符时,是否可以访问分配给的对象?