在构造函数初始值设定项中初始化成员数组

时间:2010-10-30 08:48:45

标签: c++ c++11 initializer-list ctor-initializer aggregate-initialization

class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

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

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

问题

  1. 我怎样才能做我想做的事(那个 是,初始化一个数组 构造函数(不分配元素 在身体里))。它甚至可能吗?
  2. C ++ 03标准是否说明了在ctor初始化器中初始化聚合(包括数组)有什么特别之处?或者上述代码的无效性是其他一些规则的必然结果?
  3. C ++ 0x初始化列表是否解决了这个问题?
  4. P.S。 请不要提及矢量,boost ::数组,以及它们对数组的优越性,我很清楚。

7 个答案:

答案 0 :(得分:51)

  
      
  1. 我怎样才能做我想做的事情(即在构造函数中初始化数组(不在主体中分配元素))。它甚至可能吗?
  2.   

是。它使用的是包含数组的结构。你说你已经知道了,但后来我不明白这个问题。这样,你在构造函数中初始化一个数组,而不在主体中进行赋值。这就是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():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};

答案 1 :(得分:28)

除了归零(或非POD元素,值初始化)数组外,C ++ 98不提供任何直接语法。为此你只需写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}};

答案 2 :(得分: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()) {}
};

答案 3 :(得分:3)

  1. 不幸,不幸。
  2. 你不能以你想要的方式,因为语法不允许(更多下面)。您只能使用类似ctor的初始化,并且如您所知,这不能用于初始化数组中的每个项目。
  3. 我相信,因为他们以许多有用的方式全面推广初始化。但我不确定细节。
  4. 在C ++ 03中,聚合初始化仅适用于与下面类似的语法,它必须是单独的语句,不适合ctor初始值设定项。

    T var = {...};
    

答案 4 :(得分:1)

怎么样

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

在g ++ 4.8上编译好

答案 5 :(得分:0)

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

例如,具有以下 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} } {}
};

答案 6 :(得分:-1)

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

class C 
{
public:
    int *cArray;

};

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