以下代码来自 .作者试图告诉我们,通过将一切都变成对象,我们可以防止资源泄漏。 我的问题: 为什么'cat'和'dog'的构造函数比'userresources'的构造函数更早被调用?
//: C07:Wrapped.cpp
// Safe, atomic pointers
#include <fstream>
#include <cstdlib>
using namespace std;
ofstream out("wrapped.out");
// Simplified. Yours may have other arguments.
template<class T, int sz = 1> class PWrap {
T* ptr;
public:
class RangeError {}; // Exception class
PWrap() {
ptr = new T[sz];
out << "PWrap constructor" << endl;
}
~PWrap() {
delete []ptr;
out << "PWrap destructor" << endl;
}
T& operator[](int i) throw(RangeError) {
if(i >= 0 && i < sz) return ptr[i];
throw RangeError();
}
};
class Cat {
public:
Cat() { out << "Cat()" << endl; }
~Cat() { out << "~Cat()" << endl; }
void g() {}
};
class Dog {
public:
void* operator new[](size_t sz) {
out << "allocating an Dog" << endl;
throw int(47);
}
void operator delete[](void* p) {
out << "deallocating an Dog" << endl;
::delete p;
}
};
class UseResources {
PWrap<Cat, 3> Bonk;
PWrap<Dog> Og;
public:
UseResources() : Bonk(), Og() {
out << "UseResources()" << endl;
}
~UseResources() {
out << "~UseResources()" << endl;
}
void f() { Bonk[1].g(); }
};
int main() {
try {
UseResources ur;
} catch(int) {
out << "inside handler" << endl;
} catch(...) {
out << "inside catch(...)" << endl;
}
} ///:~
最佳答案
Why the constructors of 'cat' and 'dog' are called earlier than constructor of 'useresources'?
它们的调用早于输入 UseResources
的构造函数的主体。
UseResources
有两个数据成员,它们是 PWrap<>
类模板的实例。 PWrap<T>
的构造函数实例化了多个 T
类型的对象:
ptr = new T[sz];
从而导致对 T
的构造函数进行相应数量的调用(在您的情况下为 Cat
或 Dog
)。
由于 PWrap
对象是 UseResources
的数据成员,因此它们的构造函数会在输入 UseResources
构造函数的主体之前执行。这就是 C++ 中对象构造的工作原理。
这背后的基本原理是确保当输入构造函数的主体时,所有子对象(包括基子对象和成员子对象 - 例如 Bonk
和 Og
)的构造函数都具有已完成。
这样,构造函数可以依赖使用有效的子对象,这些子对象的类不变量在执行时已经建立。
C++11 标准第 12.6.2/10 段是这样描述该过程的:
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. —end note ]
关于c++ - 首先调用哪个构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16033729/