我无法理解c ++ 11中的函数移动。
从here开始,我得到了以下内容:
虽然注意到 - 在标准库中 - 移动意味着 move-from对象保持有效但未指定的状态。哪一个 意味着,在这样的操作之后,移动的值 对象应仅被销毁或分配新值;访问它 否则产生一个未指定的值。
在我看来,在move()之后,移动的对象已经“清晰”了。但是,我在下面做了一个测试:
std::string str = "abcd";
std::move(str);
std::cout<<str;
我的屏幕上显示abcd
str
被摧毁了吗?如果是这样,我可以得到abcd
,因为我很幸运?或者我误解了函数move
?
此外,当我阅读 C ++ Primer 时,我得到了这样的代码:
class Base{/* ... */};
class D: public Base{
public:
D(D&& d): Base(std::move(d)){/* use d to initialize the members of D */}
};
我现在很困惑。如果函数move
将清除对象,则参数d
将清除,我们如何“使用d来初始化D的成员”?
答案 0 :(得分:4)
std::move
实际上并没有做任何事情。它大致类似于强制转换表达式,因为返回值是原始对象,但处理方式不同。
更准确地说,std::move
以一种形式返回对象,该形式可以使其资源因某些其他目的而“被盗”。原始对象或多或少仍然有效(你只应该为它做一些特殊的事情,尽管这主要是约定问题而不一定适用于非标准库对象),但被偷走的资源没有更长的属于它,并且通常不再被它引用。
但是! std::move
本身并没有偷窃。它只是为偷窃而设置的东西。既然你没有对结果做任何事情,更不用说可以利用这个机会的东西了,没有什么东西被偷走了。
答案 1 :(得分:1)
std :: move不会移动任何东西。 std :: move只是一个执行强制转换的函数模板。 std :: move无条件地将其参数强制转换为右值,
std::move(str);
使用此表达式,您只需从左值到右值进行类型转换。
程序中的小修改以便更好地理解。
std::string str = "abcd";
std::string str1 = std::move(str);
std::cout<<str<<std::endl;
std::cout<<str1<<std::endl;
str
按std::move
,std::string = std::move(str);
=&gt;左右对左值进行类型转换:此表达式调用实际窃取资源的string move constructor
。 str
资源(abcd)被打磨并打印出空字符串。
以下是移动功能的示例实现。请注意,它不是标准库的完整实现。
template<typename T> // C++14; still in
decltype(auto) move(T&& param) // namespace std
{
using ReturnType = remove_reference_t<T>&&;
return static_cast<ReturnType>(param);
}
将std :: move应用于对象会告诉编译器该对象是否有资格从中移动。它投向了右值。
class Base{/* ... */};
class D: public Base{
public:
D(D&& d): Base(std::move(d)){/* use d to initialize the members of D */}
};
Base(std::move(d))
它只会向上移动基类部分。
这里有一件有趣的事要向你学习。如果不使用std::move
D(D&& d): Base(d)
来调用基类析构函数,那么d将被视为左值的左值和复制构造函数,而不是移动构造函数。有关详细信息,请参阅Move constructor on derived object