据我所知,返回*this
是编写重载operator=
的标准。但这可能会促进左值的左值!
struct Foo {
Foo& operator=(const Foo &t) { return *this; }
};
int main() {
const Foo &ref = Foo();
//Foo &ref1 = Foo(); // This line won't compile.
//But the following line compiles. Isn't it dangerous?
//Also please note that if = is not overloaded, the synthesized operator= will NOT let it compile.
Foo &ref2 = (Foo() = Foo());
return 0;
}
答案 0 :(得分:7)
另一个(类似的)示例被添加到C ++ 11中,作为标准的一部分,使用rvalue流输出,返回左值引用。
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
所以std::ostream& s = std::ofstream("foo.txt") << "Oh boy";
是合法的,但会创建一个悬空参考。
我相信C ++ 11编译器会允许成员函数限制在对象是左值的情况下,这应该可以让你完全避免这个问题。以下内容仅允许在*this
为左值时进行分配,因此会阻止您意外转换。
struct Foo {
Foo& operator=(const Foo &t) & { return *this; }
};
答案 1 :(得分:1)
正如第一个答案所指出的那样,你所做的是合法的,但会导致悬挂参考。您可以在不重载赋值运算符的情况下获得相同的结果:
#include <iostream>
struct Foo {
Foo(int arg) : val(arg) { std::cout << "ctor " << val << "\n"; }
~Foo() { std::cout << "dtor " << val << "\n"; }
int val;
};
int main() {
Foo &ref = (Foo(1) = Foo(2));
std::cout << "undefined behavior: " << ref.val << "\n";
return 0;
}
产生以下输出:
ctor 1 ctor 2
dtor 2
dtor 2
未定义的行为:2
如您所见,构建Foo(1)
的临时值,然后是Foo(2)
的临时值。但是,在我们可以对引用执行任何操作之前,两个对象都会被销毁,因此后续行会导致未定义的行为。