【问题标题】:Implicit List Initialization Constructors for Structs结构的隐式列表初始化构造函数
【发布时间】:2017-11-10 02:12:34
【问题描述】:

GCC 5.4 编译这个没有任何警告(使用-std=c++11 -Wall -pedantic):

#include <iostream>

struct Coord {
    double x, y;
};

Coord origin() {
    return {0.0, 0.0};
}

int main() {
    Coord c = origin();
    std::cout << "(" << c.x << ", " << c.y << ")\n";
}

看起来{0.0, 0.0} 创建了一个 std::initializer_list 用于构造一个 Coord,即使我还没有定义这样的构造函数。

结构是否具有std::initializer_list 的隐式转换构造函数?如果是这样,何时生成此构造函数以及它如何工作的规则是什么?如果不是,为什么编译时没有警告?

【问题讨论】:

  • Aggregate initializationreturn statement, form (2)。 Brace-init 列表可以出现在return 语句中,这种情况下返回值是从它初始化的,类似于Coord ret{0.0, 0.0}; return ret;
  • 谢谢,一个指向聚合初始化页面的链接和一个关于聚合的简要总结和括号初始化列表的规则将是一个很好的答案。

标签: c++ c++11 implicit-conversion


【解决方案1】:

“类似地,我们可以初始化一个我们没有的类的对象 使用 • 成员初始化, • 复制定义了一个构造函数 初始化,或 • 默认初始化(没有初始化器或 带有一个空的初始化列表)。例如:

struct Work {
     string author;
     string name;
     int year;
};

Work s9 { "Beethoven",
          "Symphony No. 9 in D minor, Op. 125; Choral",
          1824
      };                         // memberwise initialization

Work currently_playing { s9 };   // copy initialization
Work none {};                    // default initialization”

摘自:Bjarne Stroustrup。 “C++ 编程语言,第四版。”

另外,这里是 cppreference: http://en.cppreference.com/w/cpp/language/aggregate_initialization

类类型(通常是结构或联合),没有私有或 受保护的非静态数据成员不是用户提供的、继承的或 显式(C++17 起)构造函数(显式默认或删除 允许构造函数)(C++11 起)没有虚拟、私有或 受保护 (C++17 起) 基类 无 虚成员函数 无 默认成员初始化器

这是对上述内容的扩展描述的摘录。在人类中,这意味着如果你有一个简单的类,你可以使用适当类型的列表来初始化它,以相同的方式布局。 cppref 页面显示了只要这些条件成立,您甚至可以嵌套类型。

【讨论】:

  • 不确定最后一句话是什么意思:聚合的成员不一定是聚合。
  • Work none {}; 不是聚合的默认初始化(如果您正确引用,这可能是书中的错误)。默认初始化为 Work none; ,但添加 {} 会产生不同的行为(即,每个成员都被初始化为{},在本例中这意味着 year 得到 0
  • 我的报价是复制粘贴。但它适用于 C++11。我们说的是 2017 年吗?
  • 我相信Work none{} 是 2003 年的值初始化。术语在 2003 年标准中发生了变化;在 1998 年到 2003 年间,“默认初始化”的含义大致相当于现在的值初始化;从2003年开始,默认初始化大致意思是“没有初始化,或者调用构造函数”,值初始化大致意思是“零初始化或者调用构造函数”。也许您引用的部分在该版本的修订过程中被忽略了
  • 我认为重要的是要在答案中注意结构确实具有来自std::initializer_lists 的隐式转换构造函数。正如 Igor 对这个问题所评论的那样,从 C++11 开始,这是一种特殊形式的 return 语句,它使用复制列表初始化构造值,在这种情况下使用聚合初始化,而不是尝试使用 @ 查找构造函数987654331@,因为它是唯一的参数。
猜你喜欢
  • 2015-08-08
  • 2011-01-06
  • 2011-11-03
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
  • 2017-05-02
相关资源
最近更新 更多