【发布时间】:2014-10-09 23:56:14
【问题描述】:
我有以下代码:
#include <iostream>
class foo_class {
std::string value;
public:
foo_class(const foo_class& v) : value{v.value} {
std::cout << "copy constructor" << std::endl;
}
foo_class(foo_class&& v) : value{std::move(v.value)} {
std::cout << "move constructor" << std::endl;
}
~foo_class() {
std::cout << "destructor" << std::endl;
}
foo_class(std::string v) : value{std::move(v)} {
std::cout << "type constructor" << std::endl;
}
};
struct Data {
foo_class a;
foo_class b;
};
int main() {
std::string c = "3";
Data x{c,c+"3"};
return 0;
}
重要,我用 GCC 和 Clang(分别为 4.8.2 和 3.4)和标志 -fno-elide-constructors 编译它,所以我们不会省略复制/移动构造函数。
执行结果如下:
type constructor
move constructor
destructor
type constructor
move constructor
destructor
destructor
destructor
这意味着复制构造函数根本没有被使用,即使它应该用于 struct Data 的构造函数的第一个参数。
接下来,如果我删除复制构造函数,根据我的编译器,代码仍然是合法的,但在我的理解中应该是非法的,因为在传递第一个参数时我没有强制转换为 &&(使用 std::move) Data的构造函数。
我的问题很简单: 为什么会这样? 我错过了什么吗?
【问题讨论】:
-
为什么你认为它应该是一个副本?两个参数都经过转换,所以你有两个可以移动的临时变量。
-
是否意味着如果不在Data中声明转发构造函数就无法完美转发到std::string值?
-
“完美转发”是一个适用于模板函数的概念,你没有。您的代码将字符串的内容直接移动到
x,这与一组完美的转发函数所做的事情是一样的。尽管您的类型构造函数中确实有一个额外的副本。
标签: c++ c++11 copy-constructor move-semantics move-constructor