std :: move of * this以及稍后访问类方法和字段

时间:2016-07-04 09:06:57

标签: c++ c++11 move-semantics

我理解这对代码来说是愚蠢的...但为了理解,请考虑以下事项:

#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的功能吗?

2 个答案:

答案 0 :(得分:5)

std::move实际上并没有移动任何东西,它只是转向左移到允许移动(有点用词不当,但是,嘿,我们已经坚持了它现在)。

如果你要进行实际的移动构建,你很可能会看到边界检查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

答案 1 :(得分:1)

std::move不会移动任何东西 - 它只返回一个xvalue,引用可以绑定到右值的同一个对象,以便可以调用移动的ctor或移动的operator =。

所以在你的代码中没有动作 - f只是对同一个对象的右值引用进行操作。

如果f按值接受S,则会有一个移动,您会看到i为空。