C++ CRTP initialization

我是研究僧i 提交于 2020-05-26 08:22:21

问题


i ran into a segfault running the following program

#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;
}

When i replace vec with a member of type int it doesn't segfault anymore. Why?


回答1:


Your code has undefined behavior. The problem comes from the order of the initialization; for the derived class CRTPChild, the constructor of the base class CRTPBase<CRTPChild> is invoked firstly, after that the data member vec of CRTPChild get initialized. When _func is invoked (from the constructor of the base class) vec is not initialized at all.

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.

Changing the type to int it's still UB. UB means anything is possible, it might lead to segfault or might not.




回答2:


When CRTPBase constructor is called, CRTPChild is not yet fully constructed, so calling it's member function is undefined behavior.

The way undefined behavior manifests itself depends on platform, compiler and phase of the moon.

In particular, when your member is an int, the fact that it is not yet constructed doesn't cause program to crash when you are using int - there are no invariants for int. Vector, on the other hand, has invariants, so accessing unconstructed vector will violate them, and cause incorrect memory access.




回答3:


The base-class will be initialized (i.e. constructed) before the child class. That means when you call CRTPChild::_func the CRTPChild part of the object (including the vector) haven't been constructed yet. Using the vector in any way will lead to undefined behavior.

Don't access (non-static) members of child-classes in a base-class constructor.



来源:https://stackoverflow.com/questions/61000594/can-a-crtp-base-class-constructor-access-derived-data-members

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!