类中的向量:处理复制构造函数和析构函数(C++)

Kev*_*lan 12 c++ destructor memory-management class vector

使用"big 3"(构造函数,复制构造函数,析构函数)进行简单的类:

#include <vector>
using namespace std; //actually goes in the C file that links to this header file
...
class planets(){ //stores mass and radii data for planets in a solar system.
   public:
      vector <double> mass;
      vector <double> radius;

   //constructor
   planets( int numObj ){
     for(int i=0; i<numObj; i++){
         mass.push_back(8.0); //some default values.
         radius.push_back(2.0);
     }
   }
   //copy constructor
   planets(const planets &p){
      vector <double> mass(p.mass); //copy vectors into new class.
      vector <double> radius(p.radius);
   }
  //destructor
  ~planets(){
     delete mass; //ERROR: (...) argument given to ‘delete’, expected pointer
     ~radius(); //also causes error: no match for call to(...) 
   }
}
Run Code Online (Sandbox Code Playgroud)

我计划制作一个行星矢量,因此需要"大三":

vector <planets> stars;
stars.push_back(planets(5)); //5 hypothetical planets of alpha centauri
stars.push_back(planets(8)); //our solar system. Used to be nine.
///etc.
Run Code Online (Sandbox Code Playgroud)

如何正确删除质量和半径向量,以避免内存泄漏(我是否必须)?

GMa*_*ckG 23

不,您不需要做任何事情,因为您没有管理任何资源.在管理资源时,你只会写三巨头,但vector这样做.这是三巨头写得恰到好处的,你只需要使用它.

这就是为什么单一责任原则是资源管理的关键:一旦你有一些正确管理资源的类,你可以简单地使用它而不必再担心这个资源.始终将资源管理与资源使用分开.

你需要在管理类中编写三巨头的原因是因为默认的特殊成员通常做错事(他们复制,分配,破坏值而不是值管理/指向的值.)但是一旦你的资源被包裹起来起来(比如在a std::vector),一切都很好.默认值将复制矢量,正确写入了复制.

顺便说一句,三巨头是在管理资源(复制和销毁资源)的背景下,而不是创建资源.所以它将是复制构造函数,复制赋值和析构函数,而不是默认构造函数.


有关您的信息,请按以下步骤操作:

class planets
{
public:
    // ...

    //copy constructor
    planets(const planets &p) : // use an initialization list to initialize
    mass(p.mass), // copy-construct mass with p.mass
    radius(p.radius) // copy-construct radius with p.radius
    {
        // what you had before just made a local variable, copy-constructed
        // it with p.xxx, then got released (nothing happened to your members)
    }

    //destructor
    ~planets()
    {
        // nothing to do, really, since vector destructs everything 
        // right for you, but you yes, you would delete any resources
        // you managed here
    }
};
Run Code Online (Sandbox Code Playgroud)

但是不要忘记复制赋值运算符.我推荐使用复制和交换习语,并将其留作练习.

(记住你实际上并不需要这些.)


CB *_*ley 5

“三巨头”不是您所说的。它们是:复制构造函数,复制分配运算符和析构函数。

vector实例已经是可复制和可分配的,因此您无需执行任何特殊操作,因此使用两个类型的成员,vector<double>您无需提供三者的自定义实现。

您的复制构造函数是不正确的,它不会将源向量复制到新类中,它只是从它们构造函数局部变量,然后将其丢弃。这将创建名为的局部变量,massradius用相同的名称屏蔽成员变量。

planets(const planets &p){
  vector <double> mass(p.mass); //copy vectors into new class.
  vector <double> radius(p.radius);
}
Run Code Online (Sandbox Code Playgroud)

更正确(但不必要)的是:

planets(const planets &p)
  : mass(p.mass) //copy vectors into new class.
  , radius(p.radius)
{
}
Run Code Online (Sandbox Code Playgroud)

同样,您的析构函数主体应该为空。您只能delete使用分配的指针new。由于您具有直接成员变量,因此无需采取特殊措施。