【发布时间】:2015-06-16 08:18:15
【问题描述】:
我有一个框架,将异常定义为不可复制的类,我们从中派生出可复制的类(定义复制构造函数调用不可复制的基类构造函数)
这适用于 g++,但不适用于 MSVC 2013。
以下代码将重现该问题:
#include <iostream>
using namespace std;
#if defined _MSC_VER
#define __PRETTY_FUNCTION__ __FUNCTION__
#endif
class u {
u(const u&) = delete;
const u& operator=(const u&) = delete;/* the library we use defines it as const u& */
public:
u() { cout << __PRETTY_FUNCTION__ << "def" << endl; }
protected:
explicit u(int i) { cout << __PRETTY_FUNCTION__ << "int: " << i << endl; }
};
class e : public u {
public:
e() { cout << __PRETTY_FUNCTION__ << "def" << endl; }
e(const e& _e) : u(1) { cout << __PRETTY_FUNCTION__ << "cpy" << endl; }
e& operator=(const e& _e) { cout << __PRETTY_FUNCTION__ << endl; return *this; }
};
int foo() {
e _e;
throw _e;
return 0;
}
int main() {
try {
foo();
} catch(const e& _e) {
cout << "in catch e" << endl;
} catch(...) {
cout << "in catch..." << endl;
}
#if defined _MSC_VER
cout << "press enter to exit" << endl;
cin.get();
#endif
return 0;
}
MSVC 在函数 foo() 的末尾抱怨 Error 1 error C2280: 'u::u(const u &)' : attempting to reference a deleted function。
g++ 和 clang 都编译代码,它们根本不使用复制构造函数(e 对象被移动),但如果 e 不是可复制构造的,它们都不会编译。
编辑:我已编辑代码以强制复制。
顺便说一句,如果u 复制函数未被删除(也未定义,c++11 之前的版本不可复制),MSVC 在u::u(const u&) 查找期间在链接阶段失败。 (未解决的外部)
是我的代码有缺陷,还是 MSVC 中有这个错误?
【问题讨论】:
-
这适用于 webcompiler.cloudapp.net,所以我将使用 MSVC 2015 中修复的 MSVC 错误。
-
似乎是 msvc 错误,不调用移动构造函数:stackoverflow.com/questions/21715468/can-i-throw-a-unique-ptr
-
我的第一个猜测是,当抛出
e对象时,您可能会将其捕获为u。 (不作为对u的引用。)在这种情况下,您将需要u的复制ctor。也许 gcc 和 clang 将该复制调用放在 catch 子句附近(此处不存在),但 MSVC 可能希望将其放在throw语句之后。它不会被调用,但编译器会引用它。 -
u是一个异常类,可以有效地禁用 C++11 异常处理机制。复制构造函数的const u&返回大声而明确地表明这不是故意的:开发人员无能。因此,简单的解决方案是:放弃该库。也就是说,MSVC 有许多与构造函数相关的错误,但虽然它在法律上不属于它的权利,但它在道德上是正确的,因为你已经告诉它eIS-Au没有添加数据。因此,将继承设置为非public会使代码编译,但却违背了目的。 :(
标签: c++ c++11 visual-c++