繁体   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