标准是否准确定义了对象移动后我可以对其做什么?我曾经认为你用移动物体做的所有事情都可以破坏它,但这还不够.
例如,采用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行呢?)
如果我move
shared_ptr
'进shared_ptr
''b'是'a'保证为空?
指定移动后是否为任何标准类的状态?
这个:
void foo(int &&r) {
std::cout << r << std::endl;
}
int main() {
int i = 2;
foo(std::move(i));
i = 3; //no warning. any way to get some warnings here?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有没有办法告诉编译器给我一个错误(或警告)如果我不小心使用了可变我提出以后呢?我觉得这很方便.很多时候我发现自己在其他地方移动变量,但后来我手动必须非常小心,以后我不再使用它们.现在这还没有引起任何问题,但是谁知道这一点......更好的是安全!
也许有一些预处理器技巧(或相当广泛可用的编译器扩展)存在来做这些事情?
更现实的例子:
struct HugeStorage {
std::vector<double> m_vec;
HugeStorage(std::vector<double> vec) : m_vec(std::move(vec)) { }
};
struct SmallStorage {
std::vector<double> m_vec;
SmallStorage(std::vector<double> vec) : m_vec(std::move(vec)) { }
};
std::vector<double> vec_from_data_source() {
return std::vector<double>(); //only example!!
}
int main() {
std::vector<double> vec = vec_from_data_source();
if (vec.size() > 10000) …
Run Code Online (Sandbox Code Playgroud) 可移动性允许一系列优化.然而,它认为它是以牺牲程序的静态安全性为代价来实现的:
移动后,源对象处于有效但未指定的状态,其中某些操作是合法的,但有些操作是合法的.(特别是关于这个主题的讨论,请参阅这个SO问题).看起来这个操作列表,即使它依赖于每种类型,也可以在编译时知道.然而,编译器并没有警告移动对象的错误使用(正如其他SO问题所讨论的那样).
感觉就像C++哲学一样,依靠编译器尽可能多地验证(静态知道的),其中一个例子是const-correctness enforcing.然而,似乎移动对象可以以危险的方式使用,而编译器不会尝试(或有任何意义)来捕获它们.
实际上是否存在允许编译器更好诊断的机制?如果没有,为什么没有新的限定符应用于可以在移动的对象上使用的方法,或者是否允许等效静态验证的其他机制?