C++ CRTP初始化
C++ CRTP initialization
i 运行进入段错误运行下面的程序
#include <iostream>
#include <vector>
template <typename Derived>
struct CRTPBase {
CRTPBase() {
func();
}
void func() {
static_cast<Derived*>(this)->_func();
}
};
struct CRTPChild : CRTPBase<CRTPChild>{
using CRTPBase<CRTPChild>::CRTPBase;
void _func(){
vec.resize(10);
vec[0] = 2;
}
std::vector<int> vec;
};
int main()
{
CRTPChild obj;
std::cout << obj.vec[0] << std::endl;
}
当我用 int
类型的成员替换 vec
时,它不再出现段错误。为什么?
base-class 将在子 class 之前初始化(即构造)。这意味着当您调用 CRTPChild::_func
时,对象的 CRTPChild
部分(包括向量)尚未构建。以任何方式使用向量将导致 undefined behavior.
不要在 base-class 构造函数中访问 child-classes 的(非静态)成员。
调用CRTPBase
构造函数时,CRTPChild
还没有完全构造好,所以调用它的成员函数是未定义行为。
未定义行为的表现方式取决于平台、编译器和月相。
特别是,当您的成员是一个 int 时,它尚未构造的事实不会导致程序在您使用 int 时崩溃 - int
没有不变量。另一方面,Vector 具有不变量,因此访问未构造的 vector 将违反它们,并导致不正确的内存访问。
您的代码有未定义的行为。问题来自order of the initialization;对于派生classCRTPChild
,首先调用基classCRTPBase<CRTPChild>
的构造函数,然后CRTPChild
的数据成员vec
得到初始化。当 _func
被调用时(从基础 class 的构造函数) vec
根本没有被初始化。
2) Then, direct base classes are initialized in left-to-right order as
they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
将类型更改为 int
它仍然是 UB。 UB 意味着一切皆有可能,它可能会导致段错误,也可能不会。
i 运行进入段错误运行下面的程序
#include <iostream>
#include <vector>
template <typename Derived>
struct CRTPBase {
CRTPBase() {
func();
}
void func() {
static_cast<Derived*>(this)->_func();
}
};
struct CRTPChild : CRTPBase<CRTPChild>{
using CRTPBase<CRTPChild>::CRTPBase;
void _func(){
vec.resize(10);
vec[0] = 2;
}
std::vector<int> vec;
};
int main()
{
CRTPChild obj;
std::cout << obj.vec[0] << std::endl;
}
当我用 int
类型的成员替换 vec
时,它不再出现段错误。为什么?
base-class 将在子 class 之前初始化(即构造)。这意味着当您调用 CRTPChild::_func
时,对象的 CRTPChild
部分(包括向量)尚未构建。以任何方式使用向量将导致 undefined behavior.
不要在 base-class 构造函数中访问 child-classes 的(非静态)成员。
调用CRTPBase
构造函数时,CRTPChild
还没有完全构造好,所以调用它的成员函数是未定义行为。
未定义行为的表现方式取决于平台、编译器和月相。
特别是,当您的成员是一个 int 时,它尚未构造的事实不会导致程序在您使用 int 时崩溃 - int
没有不变量。另一方面,Vector 具有不变量,因此访问未构造的 vector 将违反它们,并导致不正确的内存访问。
您的代码有未定义的行为。问题来自order of the initialization;对于派生classCRTPChild
,首先调用基classCRTPBase<CRTPChild>
的构造函数,然后CRTPChild
的数据成员vec
得到初始化。当 _func
被调用时(从基础 class 的构造函数) vec
根本没有被初始化。
2) Then, direct base classes are initialized in left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of declaration in the class definition.
将类型更改为 int
它仍然是 UB。 UB 意味着一切皆有可能,它可能会导致段错误,也可能不会。