是否不可能在没有指针的循环中构造实例?

时间:2015-08-30 17:08:58

标签: c++

此代码会爆炸,对吗?一旦循环退出,原始实例将与其所有内部成员一起死亡,因此如果它们不是POD,任何需要访问do_stuff成员的B方法都会引发分段错误,正确的吗?

void foo() {
  std::vector<B> bar;
  for (int i = 0; i < 7; i++)
    bar.push_back(B(i, i, i));
  bar[3].do_stuff();
}

那么,有没有办法在不使用指针的情况下执行此操作? 或者你必须这样做:

void foo() {
  std::vector<B*> bar;
  for (int i = 0; i < 7; i++)
    bar.push_back(new B(i, i, i));
  bar[3]->do_stuff();
  for (int i = 0; i < 7; i++)
    delete bar[i];
}

4 个答案:

答案 0 :(得分:12)

第一个代码示例有效。

std::vector复制您使用push_back传递的对象(或者移动它们与C ++ 11一起使用如果你正在推动一个临时的),只要向量本身存活,它就会保持所有实例的存活。

退出函数时会发生破坏,而不是退出循环时。

答案 1 :(得分:7)

第一个代码比第二个代码好。

B个实例将movedsince C++11 / 复制 pre-C ++ 11 到向量中,因此它们不会脱离循环后的范围 - 仅在向量超出范围之后。

如果您想获得绝对最佳的性能,请执行以下操作:

void foo() {
  std::vector<B> bar;
  bar.reserve(7);
  for (int i = 0; i < 7; i++)
    bar.emplace_back(i, i, i);
  bar[3].do_stuff();
}

这将保证只有一次重新分配,并且根据Marc Glisse的评论,元素直接在向量内部构建(而不是在那里移动或复制它们)。

答案 2 :(得分:4)

不,std::vector取得其成员的所有权,因此原始代码可以正常工作。

答案 3 :(得分:3)

std::vector复制提供给它的对象(例如push_back())并保留它们直到向量本身被销毁。

因此,只要B(B(const B&))的复制构造函数正确实现,第一个代码就完全可以了。