简体   繁体   English

如果我在 C++ 的类构造函数中显式构造它,是否会在类成员变量上调用默认构造函数?

[英]Is a default constructor called on a class member variable if I am explicitly constructing it in the class constructor in c++?

So if I have something like the following:因此,如果我有以下内容:

class MyClass{
    public:
        MyClass(){
            // do other stuff
            *oc = OtherClass(params);
        }
    private:
        OtherClass* oc;
}

When is a constructor called on OtherClass?什么时候在 OtherClass 上调用构造函数? Would its default be called once as soon as the MyClass initialization begins, and then be redefined with its value constructor during the MyClass constructor?是否会在 MyClass 初始化开始时立即调用其默认值,然后在 MyClass 构造函数期间使用其值构造函数重新定义? Or does it just not exist during "//do other stuff".或者它只是在“//做其他事情”期间不存在。 What if no default constructor is provided for other class, only a value?如果没有为其他类提供默认构造函数,只有一个值怎么办? Would it be good practice to construct it where it is defined as a member variable?在定义为成员变量的地方构造它是一种好习惯吗?

A default constructor is one that can be called without parameters.默认构造函数是可以不带参数调用的构造函数。 For example this is a default constructor:例如,这是一个默认构造函数:

struct foo { 
    foo(){}    // (should not actually be user defined)
};

This is also a default constructor:这也是一个默认构造函数:

struct bar {
    bar(int x = 42) {}
};

In your code it might be that the constructor that is called is a default constructor, but it does not matter for your code, because you do pass a parameter.在您的代码中,调用的构造函数可能是默认构造函数,但这对您的代码无关紧要,因为您确实传递了一个参数。

When is a constructor called on OtherClass?什么时候在 OtherClass 上调用构造函数?

In the line *oc = OtherClass(params);在行*oc = OtherClass(params); . .

Would its default be called once as soon as the MyClass initialization begins, and then be redefined with its value constructor during the MyClass constructor?是否会在 MyClass 初始化开始时立即调用其默认值,然后在 MyClass 构造函数期间使用其值构造函数重新定义?

If you do not provide an initializer members are default initialized.如果不提供初始化器成员,则默认初始化。 Confusingly for a pointer this means it is not initialized.对于指针来说令人困惑的是,这意味着它没有被初始化。

Or does it just not exist during "//do other stuff".或者它只是在“//做其他事情”期间不存在。

The member does exist before, but its value is indeterminate.该成员之前确实存在,但其值是不确定的。 You cannot use the value without invoking undefined behavior.您不能在不调用未定义行为的情况下使用该值。

What if no default constructor is provided for other class, only a value?如果没有为其他类提供默认构造函数,只有一个值怎么办?

See above.看上面。 The existance of a default constructor of OtherClass is not relavant here. OtherClass的默认构造函数的存在与此处无关。 It would be relevant if the member was OtherClass and not a pointer, because for members of class type default initialization calls the default constructor.如果成员是OtherClass而不是指针,这将是相关的,因为对于类类型的成员,默认初始化调用默认构造函数。

Would it be good practice to construct it where it is defined as a member variable?在定义为成员变量的地方构造它是一种好习惯吗?

It is good practice to provide an initializer for members rather than assign in the constructor:为成员提供初始化程序而不是在构造函数中分配是一种很好的做法:

class MyClass{
    public:
        MyClass() : oc(params) {
        }
    private:
    

    OtherClass oc;
}

I replaced the member with an instance rather than a pointer, because using a raw pointer as member opens up a can of worms that would require an even longer answer.我用实例而不是指针替换了成员,因为使用原始指针作为成员会打开一罐蠕虫,需要更长的答案。 For more on that read What is The Rule of Three?有关更多信息,请阅读什么是三法则? . . Note that when the member is not a pointer but a OtherClass then suddenly it matters if OtherClass has a default constructor, because if you do not provide an initializer, then the member will be default constructed.请注意,当成员不是指针而是OtherClass时, OtherClass是否具有默认构造函数突然变得很重要,因为如果您不提供初始值设定项,则该成员将被默认构造。 Though in the above I used the member initializer list and the member will be initialized by the constructor that takes one parameter.尽管在上面我使用了成员初始化器列表,并且该成员将由带有一个参数的构造函数初始化。

ÓtherClass *oc; is a pointer and as such has no constructor.是一个指针,因此没有构造函数。 It has to be initialized to a valid object before you can dereference it.必须先将其初始化为有效对象,然后才能取消引用它。

You can ensure oc is initialized by, well, initializing it:您可以确保通过初始化oc来初始化它:

MyClass() : oc(new OtherClass()) {
    ...
    *oc = OtherClass(params);
}

This will create a dummy oc when the class it created and then copy or move assign the real object to *oc later.这将在它创建的类时创建一个虚拟oc ,然后复制或移动将真实对象分配给*oc This is wasteful, so why not initialize it with the final value directly:这很浪费,为什么不直接用最终值初始化它:

MyClass() : oc(new OtherClass(params)) {
    ...
}

or if you have to compute params first:或者如果您必须先计算参数:

MyClass : oc(nullptr) {
    ...
    oc = new OtherClass(params);
}

Initializing oc with nullptr first isn't required but it is dirt cheap and it ensures accidentally using oc will access a nullptr and fail instead of oc being some random value that might not crash.不需要首先使用nullptr初始化oc ,但它非常便宜,并且它确保意外使用oc将访问 nullptr 并失败,而不是oc是一些可能不会崩溃的随机值。

You can also, and better, ensure initialization by inlineing that:您还可以并且更好地通过内联以下内容来确保初始化:

class MyClass {
    ...
    private:
        OtherClass *oc(nullptr);
}

With that the compiler will initialize oc whenever you don't initialize it in an initializer list in the constructor.这样,只要您不在构造函数的初始化程序列表中初始化oc ,编译器就会初始化它。


That said: Do you really need a pointer there?那就是说:你真的需要一个指针吗? You need a destructor, copy/move constructors and aissgnment operators to handle the pointer directly.您需要一个析构函数、复制/移动构造函数和 aissgnment 运算符来直接处理指针。 An Otherclass oc; Otherclass oc; would be much easier to deal with.处理起来会容易得多。

But if you do need a pointer then you should use a smart pointer to handle ownership for you.但是如果你确实需要一个指针,那么你应该使用一个智能指针来为你处理所有权。 That means use std::unique_ptr or more likely std::shared_ptr for it.这意味着使用std::unique_ptr或更可能的std::shared_ptr You might not even need anything past the constructor that way.那样的话,你甚至可能不需要构造函数之外的任何东西。 But think about what it means for copy/move to have the pointer shared.但是想想复制/移动共享指针意味着什么。 Read about the rule of 0/3/5 .阅读有关0/3/5 的规则

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在C ++中的父类的构造函数中构造成员对象 - Constructing a member object inside the parent class' constructor in C++ 具有数组成员变量的C ++类构造函数 - C++ Class Constructor With Array Member Variable 复制具有C ++中没有默认构造函数的成员的类的构造函数 - Copy constructor for class that has member without default constructor in C++ C++:哪个先被调用/初始化? 其成员变量的类构造函数或构造函数? - C++: Which gets called/initialized first? The Class constructor or constructor(s) of its member variable(s)? C++ 父 Class 调用默认构造函数而不是参数化构造函数 - C++ Parent Class Default Constructor Called Instead of Parameterized Constructor 如何在 C++ 的类的默认构造函数中调用成员 object 变量的参数化构造函数? - How to call parameterized constructor of member object variable in a class' default constructor in C++? C ++:为拥有类成员的类创建默认构造函数(该成员缺少默认构造函数) - C++:creating default constructor for a class that owns a class member(the member lacks default constructor) 具有构造函数的C ++类成员 - C++ class member with constructor 为什么在C ++中的另一个类的成员函数中未调用构造函数? - Why constructor is not being called in member function of another class in C++? C ++静态类成员和非默认构造函数 - C++ Static Class Member and Non-default Constructor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM