使用“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(...)
}
}
我打算制作一个行星矢量,因此需要“大3”:
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.
如何正确删除质量和半径向量,以避免内存泄漏(我是否还需要)?
答案 0 :(得分:23)
不,您不需要做任何事情,因为您没有管理任何资源。您在管理资源时只编写三巨头,但vector
正在这样做。 正确写入三巨头的那个,你只需使用它。
这就是为什么单一责任原则是资源管理的关键:一旦你有一些正确管理资源的类,你可以简单地使用它而不必再担心这个资源。 始终将资源管理与资源使用分开。
你需要在管理类中编写三巨头的原因是因为默认的特殊成员通常做错事(他们复制,分配,破坏值而不是值管理/指向的值。)但是一旦你是资源被包裹起来(就像在std::vector
中),一切都很好。默认设置将复制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
}
};
但不要忘记复制赋值运算符。我推荐copy-and-swap idiom,并将其作为练习留给你。
(记住你实际上并不需要这些。)
答案 1 :(得分:4)
您不必为您的类实现任何析构函数。矢量将被自动销毁。这与Resource Acquisition Is Initialization模式有关。
答案 2 :(得分:4)
“三巨头”不是你说的那样。它们是:复制构造函数,复制赋值运算符和析构函数。
vector
个实例已经可以复制和分配,您不需要做任何特殊的事情,因此对于vector<double>
类型的两个成员,您不需要提供三大成员的自定义实现。< / p>
您的复制构造函数不正确,它不会将源向量复制到新类中,它只是从它们构造函数本地,然后将其丢弃。这将创建名为mass
和radius
的局部变量,这些变量将使用相同的名称屏蔽成员变量。
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
的指针。由于您有直接成员变量,因此无需采取任何特殊操作。
答案 3 :(得分:2)
您的课程也可以简化:
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知道如何正确地完成所有三个操作,因此你不需要添加任何额外的代码。
答案 4 :(得分:1)
不 - 你没必要。在包含对象的析构函数之后,会自动调用成员变量的析构函数。
答案 5 :(得分:0)
在您的特殊情况下,您不必!你不是在向量中存储指针。你没有在行星类中存储指向向量的指针(也就是你没有动态分配向量&lt;&gt;对象,所以为什么要尝试删除它)。
答案 6 :(得分:0)
由于您没有new
编辑mass
,因此您无需将其删除。
此外,mass
和radius
的析构函数将自动调用,您无需明确调用它们
答案 7 :(得分:-1)
~planets(){
mass.clear();
radius.clear();
}
上面应该足够了,因为你的成员矢量对象没有任何指针。