在构造函数初始化器中初始化成员数组
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++成员初始化列表(构造函数后加冒号:)(用于在构造函数中初始化类成员变量,可以避免使用构造函数体内的赋值语句,可以确保成员变量在对象构造之初就已经被正确初始化,提高代码的性能和可读性)
Kotlin类的初始化 ② ( 主构造函数 | 主构造函数定义临时变量 | 主构造函数中定义成员属性 | 次构造函数 | 构造函数默认参数 )