使用带或不带初始值设定项列表的默认构造函数作为类数据成员的对象

发布于 2025-01-12 21:32:37 字数 1065 浏览 0 评论 0原文

对于以下程序,

#include <iostream>
using namespace std;

class university{
private:
    string uni;
public:
    university(){
        cout<<"default constructor of university is invoked"<<endl;
    }
    university(string u){
        uni =u;
        cout<<"parametrized constructor of university is invoked: "<<uni;
    }
};

class student{
private:
    university u;
public:
    student() {
        u = university("ABC");
    }
};

int main()
{
    student s;

    return 0;
}

输出为:

default constructor of university is invoked
parametrized constructor of university is invoked: ABC

但是当更改学生类的构造函数以使用初始化列表时,如下所示:

    student(): u(university("ABC")){

    }

输出为:

parametrized constructor of university is invoked: ABC

我的问题是: 对于第二种情况,当编译器在student类的私有部分运行行university u时,它是否创建类'university'的对象'u'并为其分配内存地址,或者对象是否在初始化列表中创建?如果是前者,那么为什么它不调用默认构造函数?

对于第一种情况,我有同样的问题在哪里创建对象并分配内存位置。

for the following program

#include <iostream>
using namespace std;

class university{
private:
    string uni;
public:
    university(){
        cout<<"default constructor of university is invoked"<<endl;
    }
    university(string u){
        uni =u;
        cout<<"parametrized constructor of university is invoked: "<<uni;
    }
};

class student{
private:
    university u;
public:
    student() {
        u = university("ABC");
    }
};

int main()
{
    student s;

    return 0;
}

the output is:

default constructor of university is invoked
parametrized constructor of university is invoked: ABC

but when changing the the constructor of student class to use initializer list like following:

    student(): u(university("ABC")){

    }

the output is:

parametrized constructor of university is invoked: ABC

My question is:
for the second case, when the compiler runs the line university u in the private section of student class, does it create an object 'u' of class 'university' and allocate a memory address to it, or does the object get created in the initializer list? if the former, then why didn't it call the default constructor?

for the first case, I have the same question where does the object get created and assigned a memory location.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

帅冕 2025-01-19 21:32:37

“分配内存”和“分配内存位置”与这里无关。您询问的是如何构造属于另一个类的成员的对象。试图在这里引入内存分配的主题只会让事情变得混乱。高级 C++ 技术允许“在同一位置”重复构造和销毁对象(通过放置 new 和显式析构函数调用)。实际的内存位置和对象构造/销毁完全无关紧要。它们彼此无关,如果您忘记有关内存位置的所有内容,只关注对象构造和销毁的主题,将会很有帮助。话虽如此:

对象构造函数负责构造对象的所有成员。这就是规则。没有例外。句号。

student(): u(university("ABC")){

这会起作用,但是这也会在一个令人困惑的成员中实现这一点。这说明了以下事件序列:构造一个临时的大学对象,然后复制构造学生类的实际成员,最后临时对象被销毁。这是没有必要的,只会把水搅浑。使用更简单的现代 C++ 语法,这应该是:

student(): u{"ABC"}{

这种更短、直接的语法以一种简单、简洁的方式准确地描述了正在发生的事情:对象的构造函数构造该对象的所有成员,即这里仅构造一个成员。它被称为uu 的构造函数被调用,并将字符串作为参数传递给它。大学的“参数化”构造函数被调用。构造函数的成员初始化部分只不过是一个简单的列表:这里是我的类成员,这里是它们各自构造函数的参数。阿布拉卡达布拉:它们是被建造出来的。

student() {

如果构造函数没有成员初始化部分,或者没有在初始化部分列出对象的成员,则将调用相应类成员的默认构造函数。

就是这样,这就是它的全部内容:您的类(*此处该类称为 student)具有成员,并且该类的构造函数显式初始化它们,为类成员调用相应的构造函数。如果任何类成员未在初始化部分中列出,则将调用其默认构造函数,如果类成员没有默认构造函数,则生成的代码格式错误且无法编译。

"Allocating memory" and "assigning memory location" has nothing to do with anything here. You are asking about how objects that are members of another class get constructed. Trying to pull in the subject of memory allocation here only confuses things. Advanced C++ techniques allow objects to be repeatedly constructed and destroyed "in the same place" (via placement new and explicit destructor invocations). Actual memory locations, and object constructions/destructions, are completely immaterial. They have nothing to do with each other, and it will be helpful if you simply forget everything about memory locations, and focus only on the topic of object construction and destruction. Having said all of that:

An object constructor is responsible for constructing all members of the object. That's the rule. No exceptions. Full stop.

student(): u(university("ABC")){

This will work, but this also does this in a confusing member. This spells out the following sequence of events: a temporary university object gets constructed, then copy-constructs the actual member of the student class, finally the temporary object gets destroyed. This is unnecessary and only serves to muddy the waters. Using a simpler, modern C++ syntax, this should be:

student(): u{"ABC"}{

This shorter, direct syntax, describes exactly what's going on in a simple, concise manner: the object's constructor constructs all members of this object, namely just one, here. It's called u. u's constructor gets invoked passing to it a character string as a parameter. The university's "parametrized" constructor gets called. A constructor's member initialization section is nothing more than a simple list: here are my class members, and here are the parameters to their respective constructors. Abracadabra: they're constructed.

student() {

If a constructor does not have a member initialization section, or does not list the object's member in the initialization section, the corresponding class members' default constructors get called.

That's it, that's all there is to it: your class *here the class is called student) has members, and the class's constructor explicitly initializes them, the corresponding constructor gets called, for the class members. If any class member is not listed in the initialization section its default constructor gets called, if the class member does not have a default constructor the resulting code is ill-formed and won't compile.

记忆消瘦 2025-01-19 21:32:37

成员未在构造函数主体中初始化。它们在执行构造函数主体之前初始化。当你写:

class student{
private:
    university u;
public:
    student() {
        u = university("ABC");
    }
};

那么u = unisversizy("ABC");不是初始化。由于您没有为 u 成员提供初始化程序,因此它将通过调用其默认构造函数来初始化。然后,在构造函数中,university("ABC") 通过调用另一个构造函数来创建另一个对象,并将其分配给 u

PS:在我看来,“参数化构造函数”这个术语是一个非常具有误导性的术语。教程中经常出现的“参数化构造函数”和默认构造函数之间的区别是错误的。默认构造函数是可以不带参数调用的构造函数,因此以下是默认构造函数(并且可以带参数调用):

 struct foo {
      foo(int x = 0) {} // a default constructor
                        // is this a parametrized constructor ?!?
 };

Members are not initialized in the body of the constructor. They are initialized before the body of the constructor is executed. When you write:

class student{
private:
    university u;
public:
    student() {
        u = university("ABC");
    }
};

Then u = unisversizy("ABC"); is not initialization. As you are not providing an initializer for the u member it will be initialized by calling its default constructor. Then in the constructor university("ABC") creates another object by calling the other constructor and assigns that to u.

PS: In my opinion the term "parametrized constructor" is a very misleading term. The distinction between "parametrized constructor" and a default constructor that is often made in tutorials is just wrong. A default constructor is a constructor that can be called without parameters, hence the following is a default constructor (and it can be called with parameters):

 struct foo {
      foo(int x = 0) {} // a default constructor
                        // is this a parametrized constructor ?!?
 };
驱逐舰岛风号 2025-01-19 21:32:37

情况 1

这里我们考虑以下情况:

student() {
        u = university("ABC"); //this is assignment not initialization
    }

当您写道:

student s; 

这些是上述语句的效果:

  1. student 的默认构造函数 student::student() 是叫。
  2. 进入/执行默认构造函数student::student()的主体之前,类<的默认构造函数university::university() code>university 被隐式调用。结果,您得到输出:
default constructor of university is invoked
  1. 现在,一旦 university::university() 的主体完全执行,将执行默认 ctor student::student() 的主体恢复

  2. 在执行student::student()主体时遇到以下语句:

u = university("ABC");

这是一个赋值,而不是初始化。由于表达式 university("ABC"),使用 university参数化构造函数 创建了一个临时 university 对象code>,因此您会得到输出:

parametrized constructor of university is invoked: ABC
  1. 上一步中创建的临时对象被分配给数据成员u

情况 2

这里我们考虑这样的情况:

student(): u(university("ABC")){

    }

当您写道:

student s;

发生的情况是这样的:

  1. 调用类 student默认构造函数
  2. 进入默认构造函数 student::student() 的主体之前,参数化构造函数 university::university(std::调用类 university 的 string) 是因为您有表达式 university("ABC") 并且数据成员 u已初始化。请注意,由于调用了参数化 ctor,您将得到输出:
default constructor of university is invoked
  1. 现在,当参数化 ctor 的主体完成时,执行类 student 的默认 ctor student::student() 的主体 恢复

注意

在示例的情况 2 中,您应将 student():u(university("ABC")){} 更改为:

student(): u("ABC"){

    }

Case 1

Here we consider the case where we have:

student() {
        u = university("ABC"); //this is assignment not initialization
    }

When you wrote:

student s; 

These are the effects of the above statement:

  1. Default constructor student::student() of class student is called.
  2. Before entering/executing the body of the default ctor student::student(), the default ctor university::university() of class university is implicitly called. As a result, you get the output:
default constructor of university is invoked
  1. Now once the body of university::university() is completely executed, execution of the body of default ctor student::student() is resumed.

  2. While executing the body of student::student() the following statement is encountered:

u = university("ABC");

which is an assignment and not an initialization. Due to the expression univerisity("ABC"), a temporary university object is created using the parameterized constructor of class university and hence you get the output :

parametrized constructor of university is invoked: ABC
  1. The temporary created in the last step is assigned to the data member u.

Case 2

Here we consider the case where we have:

student(): u(university("ABC")){

    }

When you wrote:

student s;

this is what happens:

  1. Default constructor of class student is called.
  2. Before entering the body of the default ctor student::student(), the parameterized constructor university::university(std::string)of class university is called because you have the expression university("ABC") and the data member u is initialized. Note that since the parameterized ctor was called you get the output:
default constructor of university is invoked
  1. Now when the body of the parameterized ctor is completed, execution of the body of default ctor student::student() of class student resumes.

Note

In case 2 of your example, you should change student():u(university("ABC")){} to just:

student(): u("ABC"){

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文