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

Does it improve safety to mark assignment operators as lvalue-only?

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

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

创建悬空引用。但是,签名:

T &operator=(T t) &

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

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

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

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 并不是一个巨大的障碍。这确实意味着 did 分配给右值的偶尔的代码现在要中断了;我个人怀疑大多数此类情况实际上是未发现的错误。


在法兰克福 (2009/07) 的 C++11 标准化期间考虑将 std 中的每个类型限制为 operator= 上的 lvalue-restricted。 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 表示 "no, that language change could break compatibility"。并且可能该提案半途而废。

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

中拒绝了它就对这个想法抱有偏见