簡體   English   中英

類中的向量:處理復制構造函數和析構函數(C ++)

[英]Vectors within classes: handling copy constructor and destructor (C++)

使用“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(...) 
   }
}

我計划制作一個行星矢量,因此需要“大三”:

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.

如何正確刪除質量和半徑向量,以避免內存泄漏(我是否必須)?

不,您不需要做任何事情,因為您沒有管理任何資源。 當你管理一個資源時,你只會寫三巨頭,但是vector正在這樣做。 這是三巨頭寫得恰到好處的,你只需要使用它。

這就是為什么單一責任原則是資源管理的關鍵:一旦你有一些正確管理資源的類,你可以簡單地使用它而不必再擔心這個資源。 始終將資源管理與資源使用分開。

你需要在管理類中編寫三巨頭的原因是因為默認的特殊成員通常做錯事(他們復制,分配,破壞值而不是值管理/指向的值。)但是一旦你的資源被包裝了up(比如在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
    }
};

但是不要忘記復制賦值運算符。 我推薦使用復制和交換習語 ,並將其留作練習。

(記住你實際上並不需要這些。)

“三巨頭”不是你說的那樣。 它們是:復制構造函數,復制賦值運算符和析構函數。

vector實例已經可以復制和賦值,你不需要做任何特殊的事情,所以有兩個類型為vector<double>成員,你不需要提供三者的自定義實現。

您的復制構造函數不正確,它不會將源向量復制到新類中,它只是從它們構造函數本地,然后將其丟棄。 這將創建稱為massradius局部變量,它們使用相同的名稱屏蔽成員變量。

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

更正確(但不必要)將是:

planets(const planets &p)
  : mass(p.mass) //copy vectors into new class.
  , radius(p.radius)
{
}

同樣,你的析構函數體應該是空的。 您只delete已使用new分配的指針。 由於您有直接成員變量,因此無需執行特殊操作。

您不必為您的類實現任何析構函數。 矢量將被自動銷毀。 這與資源獲取是初始化模式有關。

你的課也可以簡化:

class planets()
{ //stores mass and radii data for planets in a solar system.
  public:
    std::vector<double> mass;
    std::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);
    }
  }
}

你的類不包含任何資源(即指針)
因此,您無需明確管理它們。 每個班級都應該知道如何:

  • 復制自己
  • 被分配
  • 摧毀它

編譯器生成的復制構造函數賦值運算符和析構函數將自動對任何成員變量(質量和半徑)調用這些操作,因此您也不需要。 因此,在您的情況下,std :: vector知道如何正確執行所有三個操作,因此您不需要添加任何額外的代碼。

不 - 你不必。 在包含對象的析構函數之后,會自動調用成員變量的析構函數。

在您的特殊情況下,您不必! 你不是在向量中存儲指針。 你沒有在行星類中存儲指向向量的指針(也就是你沒有動態分配向量<>對象,所以為什么要嘗試刪除它)。

由於您沒有new ed mass ,因此您無需刪除它。

此外, massradius的析構函數將自動調用,您不需要明確地調用它們

  ~planets(){ 
     mass.clear();
     radius.clear();
  } 

上面應該足夠了,因為你的成員矢量對象沒有任何指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM