我刚接触C++0x,正试图理解右值引用和移动构造函数。我正在使用带有-std=c++0x选项的g++ 4.4.6,并对以下代码感到困惑:
class Foo
{
public:
Foo()
: p( new int(0) )
{
printf("default ctor\n");
}
Foo( int i )
: p( new int(i) )
{
printf("int ctor\n");
}
~Foo()
{
delete p;
printf("destructor\n");
}
Foo( const Foo& other )
: p( new int( other.value() ) )
{
printf("copy ctor\n");
}
Foo( Foo&& other )
: p( other.p )
{
printf("move ctor\n");
other.p = NULL;
}
int value() const
{
return *p;
}
private:
// make sure these don't get called by mistake
Foo& operator=( const Foo& );
Foo& operator=( Foo&& );
int* p;
};
Foo make_foo(int i)
{
// create two local objects and conditionally return one or the other
// to prevent RVO
Foo tmp1(i);
Foo tmp2(i);
// With std::move, it does indeed use the move constructor
// return i ? std::move(tmp1) : std::move(tmp2);
return i ? tmp1 : tmp2;
}
int main(void)
{
Foo f = make_foo( 3 );
printf("f.i is %d\n", f.value());
return 0;
}
我发现编译器在main()函数中使用复制构造函数来构建对象。当我在make_foo()函数中使用std::move时,主函数中使用了移动构造函数。为什么在make_foo()函数中需要使用std::move呢?我认为虽然tmp1和tmp2是make_foo()函数中的命名对象,但当它们从函数返回时应该成为临时对象。
cannot bind Foo lvalue to Foo&&
,这表明编译器仍将返回值视为左值。 - stefaanvdelete
来显式删除默认赋值运算符,而不仅仅是将它们定义为未定义(Foo& operator=( const Foo& ) = delete;
)。这样,如果您尝试使用它们,您将得到编译器错误,而不仅仅是链接器错误。 - Gorpik