【问题标题】:C++11 g++ error: use of deleted functionC++11 g++ 错误:使用已删除的函数
【发布时间】: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&lt;C&gt; m_Queue; 初始化为空。
  • g++ 5.2 同样在 m_Queue 存在时拒绝代码,并在 m_Queue 被注释掉时接受它。 clang++ 3.7 与 VC++ 2015 一样,无论如何都接受代码。此外,如果给B 提供了一个复制构造函数来打印我被调用的注释,g++ 编译代码并且测试程序将显示该复制构造函数在@987654332 中没有被调用 @.
  • @NowhereMan 我试过了。它不会改变任何东西。

标签: c++11 g++


【解决方案1】:

使用提供的代码,我无法使用 g++ 重现您对 B 中声明的队列的注释/取消注释的奇怪行为。无论队列是否被注释掉,我都会在 g++ 上收到相同的错误。

但是,您遇到的编译错误与我在测试您的代码时遇到的错误相同。此错误是由于您已显式删除 B 的复制构造函数而导致的。错误信息直接指向B的拷贝构造函数:B(const B&amp;) = delete;

请在此处查看此答案以获取更多详细信息:https://stackoverflow.com/a/14543600/1456187

至于您问题的第二部分,我只能冒险猜测,因为我手边没有 Microsoft 编译器的副本。我最好的猜测是 Microsoft 编译器允许初始化 B 数组,因为它们是在原地构造的。不过,这似乎与 '03 规范的标准背道而驰。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2020-03-26
    • 2017-06-20
    相关资源
    最近更新 更多