标准是否准确定义了对象移动后我可以对其做什么?我曾经认为你用移动物体做的所有事情都可以破坏它,但这还不够.
例如,采用swap标准库中定义的函数模板:
template <typename T>
void swap(T& a, T& b)
{
T c = std::move(a); // line 1
a = std::move(b); // line 2: assignment to moved-from object!
b = std::move(c); // line 3: assignment to moved-from object!
}
Run Code Online (Sandbox Code Playgroud)
显然,必须可以分配给移动的对象,否则第2行和第3行将失败.那么移动对象我还能做些什么呢?我在哪里可以找到标准中的这些细节?
(顺便说一句,为什么它T c = std::move(a);不是T c(std::move(a));第1行呢?)
例如:
Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
Run Code Online (Sandbox Code Playgroud) 重用移动容器的正确方法是什么?
std::vector<int> container;
container.push_back(1);
auto container2 = std::move(container);
// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize
container.push_back(2);
assert(container.size() == 1 && container.front() == 2);
Run Code Online (Sandbox Code Playgroud)
从我在C++ 0x标准草案中读到的内容; ver3似乎是正确的方法,因为移动后的对象在a中
"除非另有规定,否则此类移动物体应处于有效但未指明的状态."
我从来没有找到任何"以其他方式指定"的实例.
虽然我发现ver3有点回旋并且会有更多首选ver1,虽然vec3可以允许一些额外的优化,但另一方面很容易导致错误.
我的假设是否正确?
我之前有一个关于使用unique-ptrs的问题.我得到这个答案,建议使用仅移动对象.我定义了一个类如下:
class B {
const string objName;
public:
B ( B && ) = default;
B & operator= ( B && ) = default;
B ( const B & ) = delete;
B & operator= ( const B & ) = delete;
B(const string & name) :
objName(name) {
}
virtual ~B();
const string name() const { return objName;};
}
Run Code Online (Sandbox Code Playgroud)
我用这句话打电话给B:
class A {
A(){}
void take(B b);
}
A a;
B b("test");
cout<<b.name();
a.take(std::move(b));
cout<<b.name();
Run Code Online (Sandbox Code Playgroud)
我的问题:
我有一个表示运行时上下文并构建树的类,树根保存在unique_ptr.在构建树时,我想要提取树.这是它的外观(不可运行,这不是一个调试问题):
class Context {
private:
std::unique_ptr<Node> root{new Node{}};
public:
// imagine a constructor, attributes and methods to build a tree
std::unique_ptr<Node> extractTree() {
return std::move(this->root);
}
};
Run Code Online (Sandbox Code Playgroud)
所以我曾经std::move()从Context实例中提取根节点.
然而,有使用的替代方案,std::move()例如:
std::unique_ptr<Node> extractTree() {
// This seems less intuitive to me
return std::unique_ptr<Node>{this->root.release()};
}
Run Code Online (Sandbox Code Playgroud)
是std::move()最好的选择吗?
我有一个线程,通过这样的公共接口不断收集数据项:
class MyThread {
public:
class Item {
// ...
};
startup();
shutdown();
bool hasItems() const;
// retrieve collected items
std::vector<Item>&& items();
private:
std::mutex itemMutex;
std::vector<Item> currentItems;
};
Run Code Online (Sandbox Code Playgroud)
检索项目还应清除线程的项目列表.我返回一个右值,以便在调用端调用移动构造函数.当然,检索项应该是线程安全的,因此实现如下所示:
std::vector<MyThread::Item>&& MyThread::items() {
std::lock_guard<std::mutex> lock(itemMutex);
return std::move(currentItems);
}
Run Code Online (Sandbox Code Playgroud)
我认为锁定在这里发布得太早:函数返回rvalue'd向量,但是当std::lock_guard销毁并释放互斥锁时,移动构造函数不一定会被调用.所以从我的理解来看,这不是线程安全的.我对吗?如何使其线程安全?
我std::unordered_map使用insertoremplace方法和移动语义填充了一个。当发生关键冲突时,元素不会插入到地图中,但移动的元素无论如何都会被删除:
#include <unordered_map>
#include <iostream>
int main(){
std::unordered_map<int, std::string> m;
m.insert(std::make_pair<int, std::string>(0, "test"));
std::string s = "test";
// try insert
auto val = std::make_pair<int, std::string>(0, std::move(s));
if(m.insert(std::move(val)).second){
std::cout << "insert successful, ";
}else{
std::cout << "insert failed, ";
}
std::cout << "s: " << s << ", val.second: " << val.second << std::endl;
// try emplace
s = "test";
if(m.emplace(0, std::move(s)).second){
std::cout << "emplace successful, ";
}else{
std::cout << "emplace failed, ";
}
std::cout …Run Code Online (Sandbox Code Playgroud)