必须在构造函数初始化列表中初始化引用类型吗?

Bil*_*lie 8 c++ reference

作为自我锻炼,我写了这个简单的代码:

#include <iostream>

int gIndex = 3;

template <class T> class Array
{
public:
    explicit Array(int size);
    T& operator[](int i) { return m_data[i]; }
    T operator[](int i) const { return m_data[i]; }
    T getAnchorPoint() const { return m_data[m_anchor]; }
private:
    T* m_data;
    int m_size;
    int& m_anchor;
};

template <class T> Array<T>::Array(int size) : m_size(size), m_data(new T[size])
{
    memset(m_data, 0, size*sizeof(T));
    m_anchor = gIndex;
}

int main()
{
    Array<double> a(10);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我收到了编译错误,其中说:

error C2758: 'Array<T>::m_anchor' : must be initialized in constructor base/member initializer list

它从未发生过,是什么让我提出这个问题:

必须在构造函数初始化列表中初始化任何类成员引用类型吗?

如果是这样,为什么?这是否与某种参考类型永远不能重新分配有关?

是否有更多类型必须在构造函数初始化列表中初始化?

sya*_*yam 14

是否必须在构造函数初始化列表中初始化任何类成员引用类型?

是.

如果是这样,为什么?这是否与某种参考类型永远无法重新分配有关?

这是原因的一部分.另一部分是因为必须初始化引用,并且它没有默认构造函数.

是否有更多类型必须在构造函数初始化列表中初始化?

任何没有赋值运算符(可以是复制或移动)或默认构造函数的类型.这显然包括(但不限于)const成员,因为它们一旦构建就无法修改.


根据经验,你应该(几乎)总是喜欢在构造函数的初始化列表中初始化你的成员:为什么废弃循环首先默认构造一个对象然后只分配给它(如果这是可能的话),当你可以构造时它首先是正确的吗?

  • @ user1798362不,引用它只是别的别名.当您"分配"到引用时,您实际上已分配给它引用的对象. (3认同)

jua*_*nza 5

任何类成员引用类型都必须在构造函数初始化列表中初始化吗?

是的。

这是否与引用类型永远不能重新分配这一事实有关?

是的,加上没有“空”或默认构造供参考这一事实。它是另一个对象的别名,必须从一开始就绑定到该对象。你不能这样做(这不在类定义内):

int main()
{
  int& iref; // ERROR
  int i = 42;
  int& iref2 = i; // OK
}
Run Code Online (Sandbox Code Playgroud)

因为iref必须给某些东西起别名。