【问题标题】:Finding where a deleted function is referenced查找引用了已删除函数的位置
【发布时间】:2014-07-05 09:31:59
【问题描述】:

IDE - 桌面版 Visual Studio Express 2013

C++11

问题 - 我有一个显然被复制的类(使用复制构造函数)。如果我这样声明复制构造函数:

MyClass(const MyClass&) = delete;

它抱怨对已删除函数的引用。我现在已经检查了我的整个代码两次,找不到类的实例将被复制到哪里。

有没有办法找到引用的来源?

我已经尝试定义复制构造函数,其中有一个断点,但它从未被命中。

更新

抱歉,它确实显示了引用的位置 - 在 STL 中的某个分配器中。我设法将其追踪到 std::vector::emplace_back() 调用 - 这必须导致副本。我会调查此事。

更新 2

我真是个笨蛋——我有一个 MyClass 的向量...

【问题讨论】:

  • 那将是一个编译器错误,任何体面的编译器都会告诉你错误的确切来源。
  • 您是否尝试过清理和重建项目?
  • 搜索MyClass x=yMyClass x(y)MyClass* x = new MyClass(y)
  • 为了增加您获得有意义答案的机会(并避免投反对票),请发布sscce.org,并复制粘贴您收到的整个编译器错误消息。如果您启用所有警告,重新编译,然后复制粘贴所有警告,那就更好了。
  • 哦,还要检查您是发送到函数还是从函数返回MyClass 实例按值。我相信在这两种情况下都会隐式调用复制构造函数,以便在堆栈上复制该实例。

标签: c++ visual-c++ c++11 copy-constructor deleted-functions


【解决方案1】:

也许你遇到过以下编译器错误

http://connect.microsoft.com/VisualStudio/feedback/details/889420/issue-with-delete

它说 IDE (IntelliSense) 会抱怨而编译器没有,这可以解释为什么您没有发布任何编译器错误消息以及为什么您实际上可以首先执行带有断点的已编译程序。

错误本身很容易重现:

struct Example
{
  Example() {}
  Example(Example const &) = delete;
};

Example f()
{
  return Example();
}

int main()
{
  Example e = f();
}

像这样用 VC 2013 编译:

cl /nologo /EHsc /W4 /Za stackoverflow.cpp

没有错误,没有警告。

现在,如果您转至 http://www.compileonline.com/compile_cpp11_online.php 并使用 GCC 4.7.2 编译完全相同的代码, 会出现预期的编译器错误:

main.cpp: In function ‘Example f()’:
main.cpp:9:18: error: use of deleted function ‘Example::Example(const Example&)’
   return Example();
                  ^
main.cpp:4:3: error: declared here
   Example(Example const &) = delete;
   ^
main.cpp: In function ‘int main()’:
main.cpp:14:17: error: use of deleted function ‘Example::Example(const Example&)’
   Example e = f();
                 ^
main.cpp:4:3: error: declared here
   Example(Example const &) = delete;
   ^

所以,你实际上有两个问题:

  1. 您的编译器有错误。这只能通过升级到新版本(如果/当有可用版本)来解决。

  2. 您的代码为不允许复制的类调用复制构造函数。

第二个问题可以通过考虑 C++ 何时“间接”复制对象的规则来解决 - 或者要求存在复制构造函数即使实际复制已被优化。再次检查代码寻找以下情况:

  • 按值传递。 void f(MyClass obj);
  • 按值返回。 MyClass f();
  • 投掷。 throw MyClass();

第一个很容易解决:

void f(MyClass const &obj);

其他需要更彻底的重新设计,因为返回或扔掉直接与防止复制的想法相矛盾。

【讨论】:

  • 我认为问题更多在于我的代码中某处正在对 MyClass 执行显式或隐式复制。我想删除它,因为我希望 MyClass 是“不可复制的”。问题在于找到对已删除函数的引用。
  • @Brett:你是什么意思更多在某个地方有一个显式或隐式副本?这正是我在回答的后半部分解释的内容,我在其中给出了隐式副本的示例。
猜你喜欢
  • 2013-05-23
  • 2021-02-05
  • 1970-01-01
  • 2014-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多