返回指针的向量 - 理解

nf3*_*743 4 c++ pointers memory-management

我试图了解以下内容(让我们假装MyStorageClass很大):

class MyStorageClass
{
public:
  string x;
  string y;
  string z;
};

class storage
{
public:
  storage();
  ~storage()
  {
    vector<MyStorageClass *>::iterator it = myVec.begin(); it != myVec.end(); it++)
    {
      delete *it;
    }

  vector<MyStorageClass*> getItems()
  {
    for(int i = 0; i < 10; ++i)
    { 
      v.push_back(new MyStorageClass());
    }
    return v;
  }

private:
  vector<MyStorageClass*> v;

};



main()
{
  storage s;
  vector<MyStorageClass*> vm = s.getItems();
}
Run Code Online (Sandbox Code Playgroud)

从我的描述中,当s返回向量并被赋值给vm它时,作为副本(按值)完成.因此,如果s超出范围并将其称为析构函数,vm则拥有自己的副本,其结构不受影响.但是,通过价值传递效率不高.因此,如果您将其更改为通过引用传递:

vector<MyStorageClass*>& getItems()
{
  for(int i = 0; i < 10; ++i)
  { 
    v.push_back(new MyStorageClass());
  }
  return v;
}
Run Code Online (Sandbox Code Playgroud)

您传递v(在类Storage中)的内存位置.但是你仍然使用=运算符将它的副本分配给vmMain类中的向量.因此,如果析构函数不受影响,vm则独立于此.vStoragevm

最后,如果getItems返回一个引用,并且在main中你有以下内容:

main()
{
  storage s;
  vector<MyStorageClass*> &vm = s.getItems();
}
Run Code Online (Sandbox Code Playgroud)

现在,vm握住地址v.因此它受Storage Destructor的影响.

问题:我上面说的是真的吗?

Bjö*_*lex 7

是的,你已经正确理解了这一点.现在,如果你想把它提升到一个新的水平,首先找到原因,这是坏事:

  1. 返回指针或对类内部的引用会破坏封装.
  2. 一旦相应的s-object被销毁,你获得的引用将成为悬挂引用,从而打破引用始终有效的不变量.
  3. 通过返回一个指针向量,你会让调用者想知道天气他必须删除那些指针.

更好的解决方案是storage公开方法beginend返回相应的迭代器s.或者,您可以将Visitor -pattern用于需要操作的算法s.

此外,在您的情况下,似乎矢量s应该拥有它包含的对象.这将是一个很好的使用指标boost::ptr_vector.