标签: in-class-initialization

C++ 11:带有"= {}"的类内初始化不适用于显式构造函数

在C++ 11中,我们可以使用"brace-or-equal-initializer"(标准中的单词)进行类内初始化,如下所示:

struct Foo
{
  /*explicit*/ Foo(int) {}
};

struct Bar
{
  Foo foo = { 42 };
};
Run Code Online (Sandbox Code Playgroud)

但如果我们不发表评论explicit,它就不再编译了.GCC 4.7和4.9说:

error: converting to ‘Foo’ from initializer list would use explicit constructor ‘Foo::Foo(int)’
Run Code Online (Sandbox Code Playgroud)

我发现这令人惊讶.C++ 11标准真的是这个代码无法编译的意图吗?

删除它=修复它:Foo foo { 42 };但我个人觉得更难以向那些已经习惯了这种形式的人解释=几十年,而且由于标准指的是"支撑或平等初始化器",因此很好的旧方式在这种情况下不起作用.

c++ explicit-constructor initializer-list in-class-initialization c++11

18
推荐指数
3
解决办法
1253
查看次数

无法从成员变量中的initializer-string中推断出数组大小的原因是什么?

考虑一下代码:

struct Foo
{
    const char str[] = "test";
};

int main()
{
    Foo foo;
}
Run Code Online (Sandbox Code Playgroud)

它无法使用g ++和clang ++编译,基本上吐出来

error: array bound cannot be deduced from an in-class initializer

我明白这是标准可能会说的,但有什么特别好的理由吗?由于我们有一个字符串文字,似乎编译器应该能够毫无问题地推断出大小,类似于简单地声明一个类外const的类似C的空终止字符串的情况.

c++ c-strings in-class-initialization c++11

17
推荐指数
2
解决办法
3903
查看次数

位字段"类内初始化"导致"错误:左值作为赋值的左操作数需要左值"

struct bitfield {
  int i = 0;  // ok
  int j : 8 = 0;  // error: lvalue required as left operand of assignment
};
Run Code Online (Sandbox Code Playgroud)

使用C++ 11"类内初始化"功能初始化位字段的正确语法是什么?

c++ bit-fields in-class-initialization c++11

16
推荐指数
2
解决办法
2034
查看次数

继承 - 构造函数+非类型 - 非默认构造类型的初始化失败

我在我的项目中遇到以下错误:

error: use of deleted function ‘C::C(int)’ note: ‘C::C(int)’ is
implicitly deleted because the default definition would be ill-formed:
error: use of deleted function ‘M::M()’

这是我正在使用的代码:

struct M {
    M(int){}
    M() = delete;  // Allowing this would work.
};

struct B {
    B(int) {}
    B() = delete;
};

struct C : public B {
    using B::B;
    M n = {5};

    // C(int i) : B(i) {}  // Adding this would work
};

C c{1};
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么会这样?


很明显,语言愿意在继承的构造函数的末尾添加更多的初始化(因为它愿意调用默认的构造函数).显然,它愿意隐式地将对非默认构造函数(类初始化)的调用添加到显式定义的构造函数的末尾.但由于某种原因,我不明白,它不愿意同时做这两件事.

根据这个问题,完美转发不够完美,不应该在这里使用.

注意:在实际情况下,构造函数 …

c++ in-class-initialization c++11 inheriting-constructors

15
推荐指数
1
解决办法
182
查看次数

用户声明的默认构造函数+类内初始值设定项!=用户提供的构造函数?

锵文档整齐地解释说,

如果类或结构没有用户定义的默认构造函数,C++不允许您默认构造它的const实例([dcl.init],p9)

基本原理是如果const对象未正确初始化,则以后不能更改.以下代码仅具有用户声明的默认构造函数Test,但其所有成员都具有类内初始值设定项,

#include<iostream>

class Test
{
public:
    Test() = default;
    void print() const { std::cout << i << "\n"; }
private:
    int i = 42;   // will propagate to the default constructor!
};

int main()
{
    Test const t; // <-- Clang chokes on the const keyword, g++ does not
    t.print();    // prints 42
}
Run Code Online (Sandbox Code Playgroud)

所以用户提供默认构造函数的基本原理对我来说似乎是多余的.事实上,g ++ 4.8.1确实可以毫无问题地编译它(在线示例),尽管Clang <= 3.2没有.

问题:为什么完整的类内initalizers +用户声明的默认构造函数的组合不足以默认构造一个const对象?是否有针对C++ 14标准的修复程序?

更新:任何人都可以尝试使用Clang 3.3/3.4,看看与Clang …

c++ default-constructor in-class-initialization c++11 c++14

13
推荐指数
1
解决办法
594
查看次数

C++ 11中是否有"In class member initialization"功能?

在类初始化功能中,它允许在类本身内初始化普通成员,

struct A {
  int a = 0; // error: ISO C++ forbids in-class initialization of non-const static member ‘a’
};
Run Code Online (Sandbox Code Playgroud)

这在最新的编译器gcc-4.6(with -std=c++0x)中给出了错误.将此功能制作成C++ 11标准还是gcc仍然不支持它?

c++ in-class-initialization c++11

12
推荐指数
1
解决办法
5247
查看次数

初始化列表中的try/catch如何工作?

我们认为可能会发生初始化异常.所以我们编写try/catch块.

int f(){
    throw 1;
}

class A
{
public:
    A() try : _k(f())
    {}
    catch (int)
    {
        std::cout << "Exception 1" << std::endl;
    }

private:
    int _k;
};
Run Code Online (Sandbox Code Playgroud)

但是这个问题在一个层面上重新排除了异常.这意味着下一个代码

try
{
    A a;
} catch(int)
{
    std::cout << "Exception 2" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

将输出:

Exception 1
Exception 2
Run Code Online (Sandbox Code Playgroud)

为什么这个try/catch块的行为与普通的try/catch块不同?

完整代码示例:http://ideone.com/XjY2d

c++ exception-handling exception try-catch in-class-initialization

12
推荐指数
1
解决办法
1229
查看次数

为什么静态成员的类内初始化违反了ODR?

Stack Overflow上有几个问题,分别是"为什么我不能在C++中初始化静态数据成员".大多数的答案与标准告诉你报什么你可以做; 那些试图回答为什么通常指向一个链接(现在似乎不可用)[编辑:实际上它可用,见下文]在Stroustrup的网站上,他声明允许静态成员的类内初始化会违反一个定义规则(ODR) ).

然而,这些答案似乎过于简单化.编译器完全能够在需要时解决ODR问题.例如,请考虑C++标头中的以下内容:

struct SimpleExample
{
    static const std::string str;
};

// This must appear in exactly one TU, not a header, or else violate the ODR
// const std::string SimpleExample::str = "String 1";

template <int I>
struct TemplateExample
{
    static const std::string str;
};

// But this is fine in a header
template <int I>
const std::string TemplateExample<I>::str = "String 2";
Run Code Online (Sandbox Code Playgroud)

如果我TemplateExample<0>在多个翻译单元中实例化,编译器/链接器魔法就会启动并且我TemplateExample<0>::str在最终可执行文件中只获得一个副本.

所以我的问题是,鉴于编译器显然可以解决模板类的静态成员的ODR问题,为什么它也不能为非模板类​​执行此操作呢?

编辑:Stroustrup FAQ响应可在此处获得.相关的句子是:

但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏 …

c++ static-members one-definition-rule language-lawyer in-class-initialization

12
推荐指数
1
解决办法
792
查看次数

C++ 11"在类初始化"功能不适用于工会

最小代码示例:

struct B { 
  union U {
    struct S {} s;
    int i = 100;
  }
  u;  
};
Run Code Online (Sandbox Code Playgroud)

现在,如果我们声明一个B obj;,obj.u.i则分配一个垃圾值而不是100.请在此处查看演示.(垃圾值根据优化标志等而不同).

"类初始化"功能是否适用于联合.

  • 如果是,那么正确的语法是什么?或者这是一个g ++错误?
  • 如果不是那么呢int i = 100;

c++ unions in-class-initialization c++11

9
推荐指数
1
解决办法
279
查看次数

为什么我不能在类中初始化`const const std :: string`一个静态成员

我有以下工作代码:

#include <string>
#include <iostream>

class A {
public:
  const std::string test = "42";
  //static const std::string test = "42"; // fails
};

int main(void){
  A a;
  std::cout << a.test << '\n';
}
Run Code Online (Sandbox Code Playgroud)

是否有充分理由不能进行测试static const?我确实在c ++ 11之前理解它受到标准的限制.我认为c ++ 11引入了类内初始化,使其更友好一些.很长一段时间以来,我也没有这种语义可用于整数类型.

当然它适用于以类的形式进行的类外初始化 const std::string A::test = "42";

我想,如果你能把它变成非静态的,那么问题在于其中一个.初始化它的类外范围(通常const是在对象实例化期间创建的).但是,如果您创建一个独立于该类的任何其他成员的对象,我认为这不是问题.第二个是静态成员的多个定义.例如,如果它包含在几个中.cpp文件,登陆到几个目标文件,然后链接器将这些对象链接在一起(例如,一个可执行文件)会有麻烦,因为它们将包含相同符号的副本.据我所知,这完全等同于在标题中的类声明下提供类外权利的情况,然后在多个地方包含这个公共标题.我记得,这会导致链接器错误.

但是,现在处理此问题的责任转移到用户/程序员.如果想要拥有一个static需要提供类外定义的库,则将其编译为单独的目标文件,然后将所有其他对象链接到此文件,因此只有一个二进制定义的副本符号.

我阅读了答案中我们是否还需要单独定义静态成员,即使它们是在类定义中初始化的?我为什么不能初始化非const静态成员或类的静态数组?.

我还是想知道:

  1. 它只是一个标准的东西,还是背后有更深层次的推理?
  2. 这可以constexpr与用户定义的文字机制一起使用.clang和g ++都说变量不能有非文字类型.也许我可以做一个.(也许出于某种原因,这也是一个坏主意)
  3. 链接器只包含一个符号副本真的是一个很大的问题吗?因为它static const应该是二进制精确的不可变副本.

如果我遗失或错误理解某事,也请评论.

c++ in-class-initialization c++11

8
推荐指数
1
解决办法
2879
查看次数