【问题标题】: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() : 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 初始值设定项列表能解决问题吗?

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

【问题讨论】:

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

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


【解决方案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】:
    1. 我怎样才能做我想做的事(即在构造函数中初始化一个数组(而不是在主体中分配元素))。甚至可能吗?

    是的。它使用包含数组的结构。你说你已经知道了,但是我不明白这个问题。这样,您 在构造函数中初始化一个数组,而在主体中没有赋值。这就是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 */
    };
    

    【讨论】:

    • 我在写信时偶然发现了这一点: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】:
      1. 不,很遗憾。
      2. 你不能以你想要的方式,因为它是不允许的语法(更多见下文)。您只能使用类似 ctor 的初始化,并且如您所知,这不适用于初始化数组中的每个项目。
      3. 我相信是这样,因为它们以许多有用的方式全面概括了初始化。但我不确定细节。

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

      T var = {...};
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-26
        • 1970-01-01
        • 2020-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多