[英]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.