簡體   English   中英

在C ++構造函數中使用自動變量

[英]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構造函數,則如果成功構造sx ,則它們都將被破壞。

話雖如此,編寫此代碼的最佳方法是根本不創建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(該學生是大學班級的成員)中。 只要大學課程實例可用,其成員也將可用。 這里有一些指針可以使您的程序變得更好:

  1. 使用std :: string代替char *
  2. 我認為在大學構造函數中傳遞學生對象沒有任何意義,我認為添加addStudent方法是更好的方法
  3. 傳遞const對象引用,而不傳遞基元,由於引用,它具有更好的樣式(更封裝)和更有效

例如:

class University{
    Student s;
public:
    University(){}
    void addStudent(const Student& newStudent){
        s = newStudent;
    }

};

暫無
暫無

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

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