编辑:编译器版本已修复。
我尝试了c ++ 11的新功能,虽然我有Ubuntu 12.04,其中包含gcc 4.6.3,因此只支持c ++ 0x。我对以下示例类以及它的构造函数,赋值运算符和其他运算符有一个大致的理解问题。
class exception : public std::exception {
public:
exception(string& inMessage) throw() : message(inMessage) {
std::cout << "exception(string& inMessage): '" << message << "'" << std::endl;
}
exception(string&& inMessage) throw() : message(std::move(inMessage)) {
std::cout << "exception(string&& inMessage): '" << message << "'" << std::endl;
}
~exception() throw() { }
exception& operator =(string&& inMessage) {
std::swap(message, inMessage);
std::cout << "operator =(string&& inMessage): '" << message << "'" << std::endl;
return *this;
}
exception& operator =(string& inMessage) {
message = inMessage;
std::cout << "operator =(string& inMessage): '" << message << "'" << std::endl;
return *this;
}
exception& operator <<(string&& inMessage) {
message += inMessage;
std::cout << "operator <<(string&& inMessage): '" << message << "'" << std::endl;
return *this;
}
exception& operator <<(string& inMessage) {
message += inMessage;
std::cout << "operator <<(string& inMessage): '" << message << "'" << std::endl;
return *this;
}
char const* what() const throw() {
return message.c_str();
}
private:
string message;
};
我现在尝试使用以下
调用所有上述构造函数和运算符// constructors:
exception e1("This is the move constructor"); // move construct
exception e2 = "This is again the move constructor"; // move construct
string s("This is a lvalue string");
exception e3(s); // copy construct
// assignment:
e2 = "This is the move assignment"; // move assign
e2 = s; // copy assign
// operator <<:
e3 << "This is the rvalue reference operator >>"; // rvalue ref
e3 << s; // lvalue ref
e3 << std::move(s); // forced rvalue ref
正如我发现的那样,由于行
而无法编译exception e2 = "This is again the move constructor"; // move construct
这似乎是一个非法移动构造函数调用。据我所知,char const []被隐式转换为string&amp;&amp;就像在
中一样e3 << "This is the rvalue reference operator >>"; // rvalue ref
或
e2 = "This is the move assignment"; // move assign
为什么标准不允许这样做?
我得到的错误是:
main.cpp:40:18: error: conversion from ‘const char [33]’ to non-scalar type ‘exception’ requested
我可以通过将行更改为
来轻松解决此错误exception e2 = string("This is again the move constructor"); // move construct
答案 0 :(得分:2)
这样做的原因是,为了从exception
消息创建const char[]
,编译器必须调用两个隐式转换(一个来自{{1}到const char[]
,然后到string
),但C ++标准(包括C ++ 11)只允许一个。
有关详细信息,请参阅this question,包括C ++标准的章节和节。
答案 1 :(得分:1)
exception e2 = "This is again the move constructor"; // move construct
首先,您展示的代码没有移动构造函数。移动构造函数将是接受exception&&
的构造函数。不会为您生成默认移动构造函数,因为您已明确声明了析构函数。
上面的行尝试做的是调用默认的复制构造函数。要做到这一点,它必须从字符串文字转换为异常,这在一个步骤中是不可能的。
exception e2 = string("This is again the move constructor"); // move construct
现在这只需要一次转换。但它会调用默认的复制构造函数而不是string&&
构造函数。