- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在阅读 C++ Super-FAQ 中构造函数的初始化顺序来自网站 The C++ Programming Language。提供了以下代码。
#include <iostream>
class Y {
public:
Y();
void f();
};
Y::Y() { std::cout << "Initializing Y\n"; }
void Y::f() { std::cout << "Using Y\n"; }
class X {
public:
X(Y& y);
};
X::X(Y& y) { y.f(); }
class Z {
public:
Z();
protected:
X x_;
Y y_;
};
Z::Z()
: y_()
, x_(y_)
{ }
int main()
{
Z z;
return 0;
}
这段代码的打印序列是:
Using Y
Initializing Y
好吧,我只是无法理解这个打印序列是如何可能的,因为在类 Z 的构造函数中,首先实例化 Y 类的实例 y_ 然后实例化实例 x_ X级的就是这样。换句话说,如果要使用方法 Y::f() 首先,我需要实例化一个 Y,它肯定会调用它构造函数和打印例程 std::cout << "Initializing Y\n";。
最佳答案
由于 X x_
在 class Z
的定义中 Y y_
之前出现,因此首先构造和初始化 x_
.无论您将成员放在初始化列表 Z::Z() : y_(), x_(y_) {}
中的顺序如何,x_ 仍然首先初始化。
因为 y_
的构造函数还没有被调用,一些内部元素比如 vtable 将不会被初始化。实际上在 X 的构造函数中使用此对象可能会导致段错误。也许这个定义更适合您。
class Z {
public:
Z();
protected:
Y y_;
X x_;
};
因为 x_
定义在 y_
之后,y_
将首先被调用,您可以在 x_
中安全地使用它> 的构造函数。
您不妨阅读 Initialization order这篇文章的一部分。
编辑:C++ 重视速度并信任程序员,因此它不会尝试验证提供给它的参数。您可以将空指针转换为引用,然后使用该引用。
Y* p = 0;
X x(reinterpret_cast<Y&>(p));
这会编译,如果编译器不需要引用我们的空指针,它就不会失败。如果您将 f 设为虚拟,或尝试访问任何成员,那么这将导致段错误。
关于c++ - 对理解 C++ 代码的流程执行有一点帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41241275/
我是一名优秀的程序员,十分优秀!