sor*_*h-r 1 c++ rvalue-reference move-semantics c++11
我正在玩Move Semantics和[r | l]值引用来学习如何在真实世界的程序中使用它们.考虑以下代码:
// Item is a heavy class having move ctor and assignment but no copy.
std::map<std::string, Item*> lookup;
std::forward_list<Item> items;
void FooClass::addItem(Item&& d) {
if (lookup.find(d.getName()) == lookup.end()) {
lookup[d.getName()] = &d; //<== not safe after move?
items.push_front(std::move(d));
}
}
Run Code Online (Sandbox Code Playgroud)
我正在获取一个地址Item&&并将其存储在指针中.然后将数据移动到std::forward_list(items).我假设调用移动赋值不会影响对象的地址.那是对的吗?虽然d移动后内容不再有效.这是查找表(lookup)的内容不正确.
我假设我必须重新订购a)添加查找项目和b)移动实际数据.上面的代码并不理智.它是否正确?
我也不明白为什么我要说std::move那里.编译器应该知道这d是一个右值引用.所以它应该调用std::forward_list<T>::push_front(T&&)并移动赋值...
lookup.[d.getName()] = &d; //<== not safe after move?
Run Code Online (Sandbox Code Playgroud)
这完全不安全,但不仅仅是因为此举.与你的问题的标题相反,你没有获取右值引用的地址,你正在获取左值的地址,但是在函数返回后很快就会超出范围,这将留下一个悬空指针.考虑:
FooClass f;
f.addItem( Item() );
Run Code Online (Sandbox Code Playgroud)
这会将临时地址添加到地图中,因此,如果您取消引用指针,则程序具有未定义的行为,这是不安全的缩影.
下一行的移动可能会使事情变得更糟,因为地图中指针引用的对象可能会被移动修改,留下指向地图中移动的指针Item,但这与未定义的行为相比没有什么比较函数返回后超出范围的结果.
使代码安全是微不足道的,所以没有理由按照你的方式编写代码.
items.push_front(std::move(d));
auto& item = items.front();
lookup[item.getName()] = &item;
Run Code Online (Sandbox Code Playgroud)
现在,地图中的指针指的是一个不会超出范围的对象.只要元素在,指针就是有效的forward_list.