【发布时间】:2016-07-27 01:16:09
【问题描述】:
我有编译器:
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
微软 Visual Studio 2015 版本。 14.0。 (Visual C++ 2015)
源代码:
#include <queue>
class C
{
};
class B
{
public:
// assignment and copy prohibited
B(const B&) = delete;
B& operator=(const B&) = delete;
B(int v1, int v2) : m_V1(v1), m_V2(v2) {}
private:
int m_V1;
int m_V2;
std::queue<C> m_Queue;
};
class A
{
public:
// assignment and copy prohibited
A(const A&) = delete;
A& operator=(const A&) = delete;
A(int p1, int p2) : arrB{ {p1+1, p2+2}, {p1+3, p2+4}, {p1+5, p2+6} } { }
private:
B arrB[3];
};
1) 如果我使用 g++ 和
std::queue<C> m_Queue;
我收到以下错误:
make
g++ -std=c++11 -c test.cpp
test.cpp: In constructor ‘A::A(int, int)’:
test.cpp:29:70: error: use of deleted function ‘B::B(const B&)’
A(int p1, int p2) : arrB{ {p1+1, p2+2}, {p1+3, p2+4}, {p1+5, p2+6} } { }
^
test.cpp:11:3: error: declared here
B(const B&) = delete;
^
make: *** [test.o] Error 1
2) 如果我使用 g++ 并注释该行
//std::queue<C> m_Queue;
或者我在 Microsoft Visual Studio 2015 中使用这两种变体(注释和未注释)我没有收到任何错误。
为什么?
更新:
列表初始化使用直接列表初始化或复制列表初始化。
8.5.4 列表初始化
1 列表初始化是从花括号初始化列表初始化对象或引用。这样的初始化器 称为初始化列表,逗号分隔 列表的初始化子句称为 初始化列表。初始化列表可能为空。 列表初始化可以发生在直接初始化或 复制初始化上下文;列表初始化 直接初始化上下文称为直接列表初始化和 复制初始化上下文中的列表初始化称为 复制列表初始化。
但我不明白在我的情况下要使用哪种初始化。我以为应该按照http://en.cppreference.com/w/cpp/language/list_initialization使用direct-list-initialization@
更新 2:
8.5.1 聚合 [dcl.init.aggr]
1 聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数 (12.1),没有私有或 受保护的非静态数据成员(第 11 条),无基类(第 11 条) 10),并且没有虚函数 (10.3)。当一个聚合被初始化列表初始化时,指定 在 8.5.4 中,初始化列表的元素被视为 聚合成员的初始化器,增加下标 或会员订单。每个成员都从 相应的初始化子句。
聚合是一个数组并且每个成员都是复制初始化的 - 答案?
但这并不能解释为什么在注释行时编译没有错误:
//std::queue<C> m_Queue;
【问题讨论】:
-
尝试在
B的ctors 初始化器列表中使用大括号将std::queue<C> m_Queue;初始化为空。 -
g++ 5.2 同样在
m_Queue存在时拒绝代码,并在m_Queue被注释掉时接受它。 clang++ 3.7 与 VC++ 2015 一样,无论如何都接受代码。此外,如果给B提供了一个复制构造函数来打印我被调用的注释,g++ 编译代码并且测试程序将显示该复制构造函数在@987654332 中没有被调用 @. -
@NowhereMan 我试过了。它不会改变任何东西。