答案和評論使用std::vector
是正確的錢。請使用std::vector
而不是你想要完成的。
話雖如此,讓我們一起玩,看看我們是否可以修復你寫的代碼。
我們首先將malloc
和free
替換爲new[]
和delete[]
。但是,即使發生這種變化,也會發生同樣的問題,所以我們需要更多。
class Foo
{
float* a;
public:
Foo();
~Foo();
void allocateMemory(int size);
};
Foo::Foo()
{
a = 0;
}
Foo::~Foo()
{
delete [] a;
}
void Foo::allocateMemory(int size)
{
a = new float[size];
}
從第一眼看上去,一切似乎是確定 - 你在構造函數分配並在析構函數釋放。但是會出現的問題是當您開始在實際程序中使用Foo
對象時,並且您試圖複製Foo
對象。
例如:
int main()
{
Foo f1;
f1.allocateMemory(10); // ok
Foo f2;
f2.allocateMemory(20); // ok
}
上面應該運行正常。然而,讓我們把在一行代碼:
int main()
{
Foo f1;
f1.allocateMemory(10); // ok
Foo f2;
f2.allocateMemory(20); // ok
f1 = f2; // trouble is going to happen, but not yet
} // now it happens
一條線f1 = f2;
就是麻煩的開始位置。當您將對象分配給另一個對象時,默認情況下,所有成員都將執行淺拷貝。這意味着f1::a
和f2::a
將在分配完成後指向相同的內存。
當在f2
上調用析構函數時,則完成delete [] a;
。但是,如果在f1
上調用析構函數,它也將調用delete [] a
,其中a
指向與f2::a
指向的內存相同的內存。結果 - 雙倍空閒錯誤和未定義的行爲(可能崩潰),因爲在同一個內存塊上調用delete []
兩次。
Crashing example
所以你需要被調用時賦值(和拷貝構造)以某種方式複製數據,而不是指針值,對象之間。 f1
和f2
都需要單獨的內存區域,以便其各自的a
成員指向(內存區域具有相同的數據),以便在爲每個對象調用析構函數時,會破壞不同的內存區域。
這是C++中rule of 3的一部分。基本上,如果你的類有一個析構函數,那麼它很可能必須有一個拷貝構造函數和賦值運算符。
所以固定的Foo
類,它應該是這個樣子的時候添加拷貝構造函數和賦值操作符:
class Foo
{
float* a;
int aSize;
public:
Foo(const Foo& f); // copy constructor
Foo& operator=(const Foo& f); // assignment operator
Foo();
~Foo();
void allocateMemory(int size);
};
和實現:
#include <algorithm>
#include <cstriing>
#include "foo.h"
Foo::Foo() :a(0), aSize(0) // use member initialization list -- a good habit
{
}
Foo::~Foo()
{
delete [] a;
}
void Foo::allocateMemory(int size)
{
a = new float[size];
aSize = size;
}
Foo::Foo(const Foo& rhs) : a(0)
{
allocateMemory(rhs.aSize); // allocate memory
memcpy(a, rhs.a, aSize * sizeof(float)); // copy the data from rhs
}
Foo& Foo::operator=(const Foo& rhs)
{
Foo temp(rhs); // copy construct
std::swap(a, temp.a);
std::swap(aSize, temp.aSize);
return *this;
}
注意,有一個附加的aSize
會員。爲了有效地使用你的類,你必須保留分配的浮點數的某個地方。這對於複製正常工作是必需的。此外,使用new[]
和delete[]
代替malloc
和free
(儘管無論如何,無論您使用的是new[]/delete[]
還是malloc/free
,都必須進行相同的更改。
賦值運算符(operator=
)使用copy/swap idiom,該函數使用複製構造函數和析構函數作爲助手,以正確書寫賦值運算符。
Working example
所以你看你需要做的,使你的類不會崩潰時的所有工作?這就是爲什麼你應該使用std::vector
- 所有這些工作以及其他功能都已經爲你完成了。
爲什麼在C++中使用malloc/free而不是new/delete? – John3136
'是否有更好的可能性來分配動態分配和釋放內存?'是的,'std :: vector'。就目前而言,你的班級正在爲0/3/5違規行爲制定多項規則。 –
user657267
不要使用'new []'和'delete []',它只會讓事情變得更糟糕。 –