在周末,我正在尝试刷新我的c ++技能并学习一些c ++ 11,我偶然发现了以下问题:我无法强制我的容器类正确使用移动构造函数:
我有一个构建器类,其定义如下:
class builder
{
...
container build() const
{
std::vector<items> items;
//... fill up the vector
return container(items); //should move the vector right? wrong!
//return container(std::move(items)); also doesn't work
}
}
Run Code Online (Sandbox Code Playgroud)
类item和容器,定义如下:
class container
{
public:
container(std:vector<item> items)
: items_(items) // always invokes copy constructor on vector, never move
{ }
container(container&& rhs)
{
...
}
...
private:
std::vector<item> items_;
}
class item
{
public:
//move .ctor
item(item && rhs);
item& operator=(item && rhs);
//copy .ctor …
Run Code Online (Sandbox Code Playgroud) 我用vs2011编译了这段代码.它打印第一个构造函数然后复制构造函数.但是如果我改变函数返回a而不是ap,它将移动对象.这是一个错误还是为什么它会像这样?*ap不是rvalue吗?
struct A
{
A() { cout << "constructor" << endl;}
A(const A&) { cout << "copy constructor " << endl;}
void operator=(const A&) { cout << "assignment operator" << endl; }
A( A&&) { cout << "move copy constructor" << endl;}
void operator=(A&&) { cout << "move assignment operator" << endl;}
};
A func() { A a; A *ap = &a; return *ap; }
int main()
{
A a = func(); …
Run Code Online (Sandbox Code Playgroud) 在这里的Stack Overflow答案中,Kerrek发布了以下代码.
Foo && g()
{
Foo y;
// return y; // error: cannot bind ‘Foo’ lvalue to ‘Foo&&’
return std::move(y); // OK type-wise (but undefined behaviour, thanks @GMNG)
}
Run Code Online (Sandbox Code Playgroud)
GManNickG指出这会导致未定义的行为.
克雷克补充道
真正; 除了前进和移动,你不会真正从任何东西返回&&.这是一个人为的例子.
令我困惑的是,C++ 11标准使用函数调用,该函数调用返回rvalue引用作为xvalue表达式的示例.
xvalue("eXpiring"值)也指对象,通常接近其生命周期的末尾(例如,可以移动其资源).xvalue是涉及rvalue引用的某些表达式的结果(8.3.2).[示例:调用返回类型为右值引用的函数的结果是xvalue. - 末端的例子]
那么,当确实在未定义的行为中返回rvalue引用结果时?是否总是导致未定义的行为,除了std::move
和std::forward
和标准只是简洁?或者您是否必须访问未定义行为的返回值才能生成结果?
*"何时"是指"在什么情况下".我意识到这里没有有意义的时间概念.