std::move 个 *this 和以后访问 class 个方法和字段
std::move of *this and later access to class methods and fields
我知道用代码做事很愚蠢...但是为了便于理解,请考虑以下内容:
#include <iostream>
#include <memory>
#include <utility>
struct S;
void f( S && s );
struct S {
S() : i{std::vector<int>(10, 42)} {}
std::vector<int> i;
void call_f() { f( std::move(*this) ); }
void read() { std::cout << " from S: " << i.at(3) << std::endl; }
};
void f(S && s) { std::cout << " from f: " << s.i.at(3) << std::endl; }
int main() {
S s;
s.call_f();
s.read();
}
这为 g++ 和 clang++ 编译和 运行,而我希望 std::vector<int>
被移动。 运行 gdb 中的这个并查看内存显示 s.i
的地址在 std::move
之后未设置为零,而我预计对于非 POD 类型它会。
因此,我预计这段代码会出现段错误。
任何人都可以向我解释这种行为吗?为什么 s
及其内部字段都不无效?它是 this
的功能吗?
std::move
实际上并没有移动任何东西,它只是将右值转换为 allow 移动(有点用词不当,但是嘿,我们被困住了现在)。
如果您要进行实际的移动构造,您很可能会看到边界检查的异常 std::vector::at
。
void f(S && s) {
S steal = std::move(s);
std::cout << " from f: " << s.i.at(3) << std::endl;
}
GCC 6.1 给了我这个
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 3) >= this->size() (which is 0)
bash: line 7: 18043 Aborted (core dumped) ./a.out
std::move
不移动任何东西 - 它只是 returns 引用同一对象的 xvalue 可以绑定到右值,以便可以调用移动的 ctor 或移动的 operator=。
所以在您的代码中没有任何移动 - f
只是对同一对象的右值引用进行操作。
如果 f
按值接受 S
则将出现移动,您会看到 i
为空。
我知道用代码做事很愚蠢...但是为了便于理解,请考虑以下内容:
#include <iostream>
#include <memory>
#include <utility>
struct S;
void f( S && s );
struct S {
S() : i{std::vector<int>(10, 42)} {}
std::vector<int> i;
void call_f() { f( std::move(*this) ); }
void read() { std::cout << " from S: " << i.at(3) << std::endl; }
};
void f(S && s) { std::cout << " from f: " << s.i.at(3) << std::endl; }
int main() {
S s;
s.call_f();
s.read();
}
这为 g++ 和 clang++ 编译和 运行,而我希望 std::vector<int>
被移动。 运行 gdb 中的这个并查看内存显示 s.i
的地址在 std::move
之后未设置为零,而我预计对于非 POD 类型它会。
因此,我预计这段代码会出现段错误。
任何人都可以向我解释这种行为吗?为什么 s
及其内部字段都不无效?它是 this
的功能吗?
std::move
实际上并没有移动任何东西,它只是将右值转换为 allow 移动(有点用词不当,但是嘿,我们被困住了现在)。
如果您要进行实际的移动构造,您很可能会看到边界检查的异常 std::vector::at
。
void f(S && s) {
S steal = std::move(s);
std::cout << " from f: " << s.i.at(3) << std::endl;
}
GCC 6.1 给了我这个
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 3) >= this->size() (which is 0)
bash: line 7: 18043 Aborted (core dumped) ./a.out
std::move
不移动任何东西 - 它只是 returns 引用同一对象的 xvalue 可以绑定到右值,以便可以调用移动的 ctor 或移动的 operator=。
所以在您的代码中没有任何移动 - f
只是对同一对象的右值引用进行操作。
如果 f
按值接受 S
则将出现移动,您会看到 i
为空。