[英]Using automatic variables in C++ Constructor
因此,我讀到,使用new
意味着您必須手動管理內存,而使用自動變量意味着當變量超出范圍時它將被刪除。 如何與構造函數一起使用? 如果我使用自動變量創建對象,是否將其保存?
例如,如果我有一個課:
class University{
Student s;
public:
University(int id, char* name){
Student x(id, name);
s = x;
}
};
這行得通嗎? (假設我為Student類定義了正確的副本構造函數)。 如果這行得通,為什么有人要為此使用new
? 我是C ++的新手,如果這是一個愚蠢的問題,我深表歉意。
是的,它有效。 s
獲取默認構造的,然后僅在x
成功構造后才進行復制分配。 如果引發異常並且它逃脫了University
構造函數,則如果成功構造s
和x
,則它們都將被破壞。
話雖如此,編寫此代碼的最佳方法是根本不創建x
,而是在University
構造函數的初始化列表中初始化s
:
class University
{
private:
Student s;
public:
University(int id, char* name)
: s(id, name)
{
}
};
話雖如此,您的問題是關於new
。 等效項如下所示:
class University
{
private:
Student *s;
public:
University(int id, char* name)
: s(new Student(id, name))
{
try
{
// do something that might throw an exception
}
catch (...)
{
delete s;
throw;
}
}
~University()
{
delete s;
}
};
try/catch
的原因是,如果構造函數拋出異常,則不會調用析構函數。
可以使用自動變量將以上內容替換為以下內容:
class University
{
private:
std::auto_ptr<Student> s; // or std::unique_ptr if you are using C++11
public:
University(int id, char* name)
: s(new Student(id, name))
{
}
};
無論是否拋出異常,如果s
成功構建,都將對其進行銷毀。
這行得通嗎?
是的,它可以工作,但是通過x
使用的間接
Student x(id, name);
s = x;
在構造函數體內,是完全沒有必要的! 為了濃縮構造函數的主體代碼並避免引用初始化問題,我將使用成員初始化程序列表 :
class University{
Student s;
public:
University(int id, char* name) : s(id,name) {
// ^^^^^^^^^^^^ Use member initializer list!
}
};
您無需在構造函數主體中使用該中介實例。
如果這行得通,為什么有人要為此使用new?
恕我直言,沒有確定的方法。 有時對於某些用例/要求,可能希望在堆上創建Student
實例,而不是使用堆棧分配的實例。
注意:
一所University
通常有很多 Student
訂閱,而不僅僅是一個! 這意味着您將需要以某種方式保留University
實例中的學生列表。
你最好應該考慮有類似
class University {
std::vector<Student> students_;
std::string universityName_;
public:
University(std::string universityName) : universityName_(universityName) {}
void addStudent(const Student& newStudent) {
students_.push_back(newStudent);
}
void addStudent(int id, const char* name) {
students_.push_back(Student(id,name));
}
};
您的代碼的天真解釋是x
是University(...)構造函數堆棧上的自動對象。 當構造函數調用結束時, x
對象將被銷毀。 但是,您還將x
對象分配給s
並且s
被聲明為University對象的成員變量,從天真的角度來說,它將保留它。
(除非為Student類重新定義了=
運算符,以使其執行不同尋常的操作)。
如果使用推薦的初始化列表
University(int id, char* name)
: s(id, name)
{
}
,其語義將有所不同,因為s
將直接從(id, name)
構造。 如果像您一樣分配它,則s
將首先使用其默認構造函數(如果有)構造,然后從x
變量分配給。
是的,那行得通。 您正在創建一個臨時學生,然后將其復制到s(該學生是大學班級的成員)中。 只要大學課程實例可用,其成員也將可用。 這里有一些指針可以使您的程序變得更好:
例如:
class University{
Student s;
public:
University(){}
void addStudent(const Student& newStudent){
s = newStudent;
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.