在构造函数初始化器中初始化成员数组

Posted

技术标签:

【中文标题】在构造函数初始化器中初始化成员数组【英文标题】:Initializing a member array in constructor initializer 【发布时间】:2011-05-02 18:12:23 【问题描述】:
class C 

public:
 C() : arr(1,2,3) //doesn't compile

    /*
    C() : arr1,2,3 //doesn't compile either

    */
private:
 int arr[3];
;

我相信原因是数组只能用=语法初始化,即:

int arr[3] = 1,3,4;

问题

    我怎样才能做我想做的事(即 是,初始化一个数组 构造函数(不分配元素 在身体里))。甚至可能吗? C++03 标准对在 ctor 初始化程序中初始化聚合(包括数组)有什么特别的规定吗?或者上述代码的无效是其他一些规则的必然结果? C++0x 初始值设定项列表能解决问题吗?

P.S.请不要提及向量,boost::arrays,以及它们对数组的优越性,我很清楚。

【问题讨论】:

你是否也知道 boost 固定大小数组的存在,它提供了构造函数? @Benoît:我是。但我需要了解普通数组:) 【参考方案1】:

我发现这个问题非常有用,但没有找到成员数组元素是没有默认构造函数和删除复制/移动构造函数的对象的示例。换句话说,初始化成员数组的示例没有不必要的对象复制。

例如,具有以下 A 类:

class A 
  public:
    int v;
    A(int v) : v(v)  
    A() = delete;
    A(A &&) = delete;
    A(const A &) = delete;
    A &operator =(A &&) = delete;
    A &operator =(const A &) = delete;
;

使用非默认构造函数进行就地初始化如下所示:

class B 
  public:
    A a[3];
    B() : a  1, 2, 3  
;

【讨论】:

【参考方案2】:

您想在构造函数中初始化一个整数数组吗?将其指向一个静态数组。

class C 

public:
    int *cArray;

;

C::C 
    static int c_init[]1,2,3;
    cArray = c_init;

【讨论】:

这是个坏主意,因为如果您更改该数组,该类的所有实例都会更改它。【参考方案3】:

怎么样

...
  C() : arr 1,2,3 

...

?

在 g++ 4.8 上编译良好​​p>

【讨论】:

这是标准吗?请引用相关条款好吗? 不能在 Visual C++ 上编译。【参考方案4】:

C++98 除了对数组进行归零(或对非 POD 元素进行值初始化)之外,不提供任何直接语法。为此,您只需写C(): arr()

我认为 Roger Pate 对 C++0x 聚合初始化的所谓限制是错误的,但我懒得查找或检查它,这没关系,不是吗? 编辑:Roger 说的是“C++03”,我把它误读为“C++0x”。对不起,罗杰。 ☺

当前代码的 C++98 解决方法是将数组包装在 struct 中,并从该类型的静态常量初始化它。无论如何,数据必须驻留在某个地方。袖口它可能看起来像这样:

class C 

public:
    C() : arr( arrData ) 

private:
     struct Arr int elem[3]; ;
     Arr arr;
     static Arr const arrData;
;

C::Arr const C::arrData = 1, 2, 3;

【讨论】:

我说 0x 有什么限制? @Roger:“聚合初始化 ... 不适合 ctor 初始化程序”。只需检查 C++0x 草案 N3126,mem-initializer 的语法,在 §12.5.2/1 中,包括使用 braced-init-list。跨度> 我这句话的前两个词是In C++03, ...【参考方案5】:
    我怎样才能做我想做的事(即在构造函数中初始化一个数组(而不是在主体中分配元素))。甚至可能吗?

是的。它使用包含数组的结构。你说你已经知道了,但是我不明白这个问题。这样,您 在构造函数中初始化一个数组,而在主体中没有赋值。这就是boost::array 所做的。

C++03 标准对在 ctor 初始化程序中初始化聚合(包括数组)有什么特别的规定吗?或者上述代码的无效是其他一些规则的必然结果?

mem-initializer 使用直接初始化。第 8 条的规则禁止这种事情。我不太确定以下情况,但一些编译器确实允许这样做。

struct A 
  char foo[6];
  A():foo("hello")   /* valid? */
;

有关详细信息,请参阅this GCC PR。

C++0x 初始化列表能解决问题吗?

是的,他们有。但是,我认为您的语法无效。您必须直接使用大括号来触发列表初始化

struct A 
  int foo[3];
  A():foo1, 2, 3  
  A():foo(1, 2, 3)   /* invalid */
;

【讨论】:

我在写信时偶然发现了这一点:char * const foo[6]; 班级成员。它需要初始化器才能在 C++11 中编译。【参考方案6】:

解决方法:

template<class T, size_t N>
struct simple_array  // like std::array in C++0x
   T arr[N];
;


class C : private simple_array<int, 3> 

      static simple_array<int, 3> myarr() 
           simple_array<int, 3> arr = 1,2,3;
           return arr;
      
public:
      C() : simple_array<int, 3>(myarr()) 
;

【讨论】:

【参考方案7】:
    不,很遗憾。 你不能以你想要的方式,因为它是不允许的语法(更多见下文)。您只能使用类似 ctor 的初始化,并且如您所知,这不适用于初始化数组中的每个项目。 我相信是这样,因为它们以许多有用的方式全面概括了初始化。但我不确定细节。

在 C++03 中,聚合初始化仅适用于类似于下面的语法,它必须是单独的语句并且不适合 ctor 初始化程序。

T var = ...;

【讨论】:

以上是关于在构造函数初始化器中初始化成员数组的主要内容,如果未能解决你的问题,请参考以下文章

基类构造函数的派生类成员初始化

c语言如何对结构体某一成员初始化

C ++:数组的构造函数/初始化程序?

C++成员初始化列表(构造函数后加冒号:)(用于在构造函数中初始化类成员变量,可以避免使用构造函数体内的赋值语句,可以确保成员变量在对象构造之初就已经被正确初始化,提高代码的性能和可读性)

静态构造函数, 静态成员初始化/调用顺序

Kotlin类的初始化 ② ( 主构造函数 | 主构造函数定义临时变量 | 主构造函数中定义成员属性 | 次构造函数 | 构造函数默认参数 )