标签: 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];
};
Run Code Online (Sandbox Code Playgroud)

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

int arr[3] = {1,3,4};
Run Code Online (Sandbox Code Playgroud)

问题

  1. 我该怎么做我想做的事情(也就是说,在构造函数中初始化一个数组(不在主体中分配元素)).它甚至可能吗?
  2. C++ 03标准是否对在ctor初始化器中初始化聚合(包括数组)有什么特别之处?或者上述代码的无效性是其他一些规则的必然结果?
  3. C++ 0x初始化列表是否解决了这个问题?

PS请不要提及矢量,boost ::数组,以及它们对数组的优越性,我很清楚.

c++ initializer-list ctor-initializer aggregate-initialization c++11

92
推荐指数
3
解决办法
14万
查看次数

什么时候私有构造函数不是私有构造函数?

假设我有一个类型,我想将其默认构造函数设为私有.我写了以下内容:

class C {
    C() = default;
};

int main() {
    C c;           // error: C::C() is private within this context (g++)
                   // error: calling a private constructor of class 'C' (clang++)
                   // error C2248: 'C::C' cannot access private member declared in class 'C' (MSVC)
    auto c2 = C(); // error: as above
}
Run Code Online (Sandbox Code Playgroud)

大.

但是,构造函数结果证明不像我想象的那样私密:

class C {
    C() = default;
};

int main() {
    C c{};         // OK on all compilers
    auto c2 = C{}; // OK on …
Run Code Online (Sandbox Code Playgroud)

c++ default-constructor language-lawyer aggregate-initialization c++11

85
推荐指数
3
解决办法
4138
查看次数

缩小C++ 0x中的转换.它只是我,还是听起来像一个突破性的变化?

的C++ 0x将会使下面的代码和类似代码形成不良的,因为它需要一个所谓的收缩转换double一个int.

int a[] = { 1.0 };
Run Code Online (Sandbox Code Playgroud)

我想知道这种初始化是否在现实代码中被大量使用.这个改变将破坏多少代码?如果您的代码受到影响,是否需要在代码中修复此问题?


供参考,参见n3225的8.5.4/6

缩小转换是隐式转换

  • 从浮点类型到整数类型,或
  • 从long double到double或float,或从double到float,除非source是常量表达式,转换后的实际值在可以表示的值范围内(即使它不能精确表示),或者
  • 从整数类型或无范围枚举类型到浮点类型,除非源是常量表达式,转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值,或者
  • 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非source是常量表达式,并且转换后的实际值将适合目标类型并且将在生成原始值时生成原始值转换回原始类型.

c++ survey aggregate-initialization c++11

82
推荐指数
5
解决办法
7万
查看次数

删除了默认构造函数.仍然可以创建对象......有时候

c ++ 11统一初始化语法的天真,乐观和哦......错误的观点

我认为,因为C++ 11用户定义的类型对象应该使用新{...}语法而不是旧(...)语法构造(除了构造函数重载std::initializer_list和类似参数(例如std::vector:size ctor vs 1 elem init_list ctor)).

好处是:没有狭义的隐式转换,最烦人的解析没有问题,一致性(?).我没有看到任何问题,因为我认为它们是相同的(除了给出的例子).

但他们不是.

一个纯粹疯狂的故事

{}调用默认的构造函数.

......除非:

  • 删除默认构造函数
  • 没有定义其他构造函数.

然后它看起来像是值而不是初始化对象?...即使对象已经删除了默认构造函数,{}也可以创建一个对象.这不是打败了删除的构造函数的全部目的吗?

......除非:

  • 该对象有一个删除的默认构造函数和
  • 其他构造函数定义.

然后失败了call to deleted constructor.

......除非:

  • 该对象有一个删除的构造函数和
  • 没有其他构造函数定义和
  • 至少是一个非静态数据成员.

然后失败并丢失了字段初始值设定项.

但是,您可以使用它{value}来构造对象.

好吧也许这与第一个异常相同(值init对象)

......除非:

  • 该类有一个删除的构造函数
  • 并且至少有一个数据成员默认初始化.

然后也{}不能{value}创建一个对象.

我相信我错过了一些.具有讽刺意味的是,它被称为统一初始化语法.我再说一遍:UNIFORM初始化语法.

这种疯狂是什么?

情景A.

删除默认构造函数:

struct foo {
  foo() = delete;
};

// All bellow OK (no errors, no warnings) …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer aggregate-initialization list-initialization c++14

49
推荐指数
3
解决办法
6977
查看次数

std :: array初始化中的brace elision

假设有一个std::array要初始化的东西.如果使用双括号可以:

std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
Run Code Online (Sandbox Code Playgroud)

在良好的旧聚合初始化中使用单个括号也是可以的,因为括号省略将处理缺少的大括号:

std::array<int, 2> x = {0, 1};
Run Code Online (Sandbox Code Playgroud)

但是,使用单个括号的列表初始化是否可以?GCC接受它,Clang拒绝它"在使用直接列表初始化时不能省略关于子对象初始化的大括号".

std::array<int, 2> x{0, 1};
Run Code Online (Sandbox Code Playgroud)

提到括号内容的标准中唯一的部分是8.5.1/12,其中说:

使用赋值表达式初始化聚合成员时,将考虑所有隐式类型转换(第4节).如果赋值表达式可以初始化成员,则初始化成员.否则,如果成员本身是子集合,则假定使用大括号,并考虑赋值表达式初始化子集合的第一个成员.

8.5.1是关于聚合初始化的,所以应该意味着Clang是正确拒绝的,对吗?没那么快.8.5.4/3说:

列表初始化对象或类型T的引用定义如下:

[...]

- 否则,如果T是聚合,则执行聚合初始化(8.5.1).

我认为这意味着与聚合初始化完全相同的规则,包括括号elision,适用,意味着GCC是正确的接受.

我承认,措辞不是特别清楚.那么,哪个编译器正确处理第三个片段呢?括号省略是否在列表初始化中发生,或者不是?

c++ language-lawyer aggregate-initialization c++11 list-initialization

46
推荐指数
2
解决办法
5635
查看次数

是否可以防止遗漏聚合初始化成员?

我有一个包含许多相同类型成员的结构,就像这样

struct VariablePointers {
   VariablePtr active;
   VariablePtr wasactive;
   VariablePtr filename;
};
Run Code Online (Sandbox Code Playgroud)

问题是,如果我忘记初始化结构成员之一(例如wasactive),如下所示:

VariablePointers{activePtr, filename}
Run Code Online (Sandbox Code Playgroud)

编译器不会抱怨它,但我会有一个部分初始化的对象。我怎样才能防止这种错误?我可以添加一个构造函数,但它会重复两次变量列表,所以我必须输入所有这些三次!

如果有 C++11 的解决方案(目前我仅限于该版本),还请添加C++11答案。不过,也欢迎使用最新的语言标准!

c++ aggregate-initialization

44
推荐指数
3
解决办法
1876
查看次数

具有非静态成员初始值设定项的类的C++ 11聚合初始化

是否允许标准:

struct A
{
  int a = 3;
  int b = 3;
};

A a{0,1}; // ???
Run Code Online (Sandbox Code Playgroud)

这个课程仍然是聚合的吗? clang接受此代码,但gcc不接受.

c++ gcc aggregate-initialization c++11 c++14

33
推荐指数
1
解决办法
6519
查看次数

如何在添加自定义构造函数的同时保持聚合初始化?

如果我没有在结构中定义构造函数,我可以通过选择某个值来初始化它,如下所示:

struct Foo {
    int x, y;
};

Foo foo = {.y = 1};
Run Code Online (Sandbox Code Playgroud)

但是如果我添加新的默认构造函数,那么我就会失去这个功能:

struct Bar {
    int x, y;
    Bar(int value) : x(value), y(value) {}
};

Bar bar1 = 1;
Bar bar2 = {.y = 2}; // error: a designator cannot be used with a non-aggregate type "Bar"
Run Code Online (Sandbox Code Playgroud)

是不是两种方法都可以呢?

我尝试添加默认构造函数Bar () {},但似乎也不起作用。

c++ constructor aggregate-initialization

32
推荐指数
2
解决办法
3510
查看次数

Visual Studio 2019无法正确处理结构的动态数组的聚合初始化

如果使用VC ++ 2017编译,下面的代码将显示垃圾(或零),如果使用GCC或Clang(https://rextester.com/JEV81255)进行编译,则以下代码将显示“ 1122” 。是VC ++的bug还是我在这里遗漏了一些东西?

#include <iostream>

struct Item {
    int id;
    int type;
};

int main()
{
    auto items = new Item[2]
    {
        { 1, 1 },
        { 2, 2 }
    };

    std::cout << items[0].id << items[0].type;
    std::cout << items[1].id << items[1].type;
}
Run Code Online (Sandbox Code Playgroud)

同时,如果元素属于原始类型(例如int),则也可以使用。

c++ new-operator visual-c++ compiler-bug aggregate-initialization

26
推荐指数
1
解决办法
354
查看次数

我可以引用初始化列表的先前成员吗?

假设我想引用initializer_list我已定义的成员.我可以做吗?

这段代码在Visual Studio和gcc中编译并给出了预期的"13 55" ,我只想知道它是合法的:

const int foo[2] = {13, foo[0] + 42};
Run Code Online (Sandbox Code Playgroud)

c++ arrays initializer-list language-lawyer aggregate-initialization

24
推荐指数
1
解决办法
558
查看次数