Bas*_*rel 14 c++ visual-c++ c++11
我有一个框架,它将异常定义为一个不可复制的类,我们从中派生了一个可复制的类(定义一个复制构造函数,调用一个非复制的基类构造函数)
这适用于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;
}
Run Code Online (Sandbox Code Playgroud)
MSVC Error 1 error C2280: 'u::u(const u &)' : attempting to reference a deleted function在函数foo()结束时抱怨.
g ++和clang都编译代码,并且它们根本不使用复制构造函数(移动e对象),但如果e不是可复制构造的,它们都不会编译.
编辑:我编辑了代码以强制复制.
顺便说一句,如果u没有删除复制功能(也没有定义,前c ++ 11不可复制),MSVC在u::u(const u&)查找期间在链接阶段失败.(未解决的外部)
我的代码中是否存在缺陷,或者MSVC中存在此错误?
首先,e两者u都有用户声明的复制构造函数。这意味着它们没有隐式生成的移动构造函数或移动赋值运算符。(因此,您的主张“e物体已移动”是错误的;下面将对此进行详细介绍)。
e是可复制的,u是不可复制的。e被认为是可移动的,因为如果没有移动构造函数,移动就会退回到复制。
根据C++14的[except.throw]部分(C++11中相同),抛出异常时对象的初始化相当于:
e temp = e_; // (1)
const e& _e = temp; // (2)
Run Code Online (Sandbox Code Playgroud)
对于 (1),不会创建临时文件,因为e_和temp具有相同的类型。
对于(2)来说是直接绑定:_e指的是temp直接的,不再有临时的。
您可能还记得 (1) 是复制省略上下文。这意味着必须存在可访问的复制或移动构造函数;但编译器可以跳过对该构造函数的调用,并为两个对象使用相同的内存空间。
这可能就是您所说的“e对象已移动”的意思:您看到它没有被复制,但假设移动了,而实际上它是复制省略。
总而言之:throw-catch工作的唯一要求是e具有可调用的移动构造函数或复制构造函数。(这个构造函数实际上可能不会被调用,但它必须存在)。
事实上,您e确实有一个可调用的复制构造函数,因此代码是正确的,并且您尝试的 MSVC 版本存在错误。
如果您仍然可以访问该版本,那么尝试实际编写e temp = e_; const e& _e = temp;并查看该代码是否生成相同的错误消息会很有趣。这将显示该错误是否与编译器的复制初始化实现有关,而不是其抛出的错误。
| 归档时间: |
|
| 查看次数: |
518 次 |
| 最近记录: |