emplace_back和std::move结合使用的一些注意事项

使用emplace_back和std::move的一些注意事项

看下面示例

class Test {
public:
  Test(int a) : a_(a) { std::cout << "Test() a:" << a_ << std::endl; }

  Test(const Test &t) {
    this->a_ = t.a_;
    std::cout << "copy" << std::endl;
  }

  /*
  Test(Test &&t) {
    this->a_ = t.a_;
    t.a_ = -1;
    std::cout << "move" << std::endl;
  }
  */

  ~Test() {}

private:
  int a_ = -1;
};

int main() {
  std::vector tests;
  tests.reserve(10);

  Test test1(100);
  tests.push_back(test1);
  std::cout << std::endl;
  Test test2(200);
  tests.emplace_back(test2);

  std::cout << std::endl;
  Test test3(300);
  tests.push_back(std::move(test3));
  std::cout << std::endl;
  Test test4(400);
  tests.emplace_back(std::move(test3));

  return 0;
}

运行结果:

Test() a:100
copy

Test() a:200
copy

Test() a:300
copy

Test() a:400
copy

tests.reserve(10); 这句一定要加,不然后面测试向vector中添加东西的时候vector会扩容并且拷贝元素,影响测试结果。

  • 在Test类没有移动构造的场景下,使用push_back和emplace_back不带std::move,效果相同,都是做一次拷贝构造
  • 在Test类没有移动构造的场景下,使用push_back和emplace_backstd::move,效果相同,都是做一次拷贝构造

这里说明个很简单的道理,不是说把push_back替换成emplace_back就能做性能优化了

再看如果给Test类加上移动构造函数。

  Test(Test &&t) {
    this->a_ = t.a_;
    t.a_ = -1;
    std::cout << "move" << std::endl;
  }

然后再执行,结果:

Test() a:100
copy

Test() a:200
copy

Test() a:300
move

Test() a:400
move
  • 在Test类移动构造的场景下,使用push_back和emplace_back不带std::move,效果相同,都是做一次拷贝构造
  • 在Test类移动构造的场景下,使用push_back和emplace_backstd::move,效果相同,都是做一次移动构造
    这里又说明了一个简单道理,emplace_back和std::move结合使用,一定要给类加上移动构造函数,如果没有移动构造,就会退化成拷贝构造。

再看emplace_back原地构造的能力:

  std::cout << std::endl;
  tests.emplace_back(500);

运行结果:

Test() a:500

这里又说明了一个简单道理,使用emplace_back直接原地构造效果最佳,只会产生一次默认构造。

你可能感兴趣的:(c++,linux)