所以我读到使用new
意味着您手动必须管理内存而使用自动变量意味着当变量超出范围时它将被删除。这如何与构造函数一起工作?如果我使用自动变量创建对象,是否会保存?
例如,如果我有一个班级:
class University{
Student s;
public:
University(int id, char* name){
Student x(id, name);
s = x;
}
};
这会有用吗? (假设我为Student类设置了一个正确定义的复制构造函数)。如果这确实有效,为什么有人会想要new
呢?我对C ++很新,所以如果这是一个愚蠢的问题,请道歉。
答案 0 :(得分:4)
是的,它有效。 s
首先获取默认构造,然后仅在成功构造x
时进行复制分配。如果引发异常并且它逃脱了University
构造函数,则s
和x
如果成功构建,则会被破坏。
话虽这么说,写这个的最好方法是根本不创建x
,并在s
构造函数的初始化列表中初始化University
:
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
如果成功构建都将被破坏。
答案 1 :(得分:3)
这会有用吗?
是的,它会起作用,但通过x
使用
Student x(id, name);
s = x;
在构造函数体中,完全没必要!我要做的是,只是为了压缩构造函数体代码,并避免引用初始化问题,使用member initializer list:
class University{
Student s;
public:
University(int id, char* name) : s(id,name) {
// ^^^^^^^^^^^^ Use member initializer list!
}
};
您不需要构造函数体中的中间实例。
哎呀,没有办法告诉你,恕我直言。有时对于某些用例/需求,可能需要在堆上创建如果这确实有效,为什么有人想在这上面使用new?
Student
的实例,而不是使用堆栈分配的实例。
ATTENTIVELY NOTE:
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));
}
};
答案 2 :(得分:1)
您的代码的天真解释是x
是University(...)构造函数堆栈上的自动对象。当构造函数调用结束时,x
对象将被销毁。
但是,您也将x
对象分配给s
,并且s
被声明为大学对象的成员变量,天真地说,它将保留它。
(除非为Student类重新定义=
运算符以执行异常操作。)
如果您使用推荐的初始化列表
University(int id, char* name)
: s(id, name)
{
}
,
语义将有所不同,因为s
将直接从(id, name)
构建。
如果你像那样分配它,那么s
将首先用它的默认构造函数构造,如果它有一个,然后从x
变量赋值。
答案 3 :(得分:-1)
是的,那会有效。您正在创建一个临时学生,然后将其复制到s,即大学课程成员的学生对象。 只要有大学课程的实例,其成员也可以使用。 以下是使您的计划更好的几点建议:
例如:
class University{
Student s;
public:
University(){}
void addStudent(const Student& newStudent){
s = newStudent;
}
};