编译器不会使用复制分配来代替移动?
Compiler won't use copy assignment instead move?
我有一个 class,其中明确删除了移动分配,因为对象不应该是可移动的。但是如果我使用 RVO 分配给这个 class 的实例,编译器会给我错误:
main.cpp:12:16: note: candidate function has been explicitly deleted
编译器也提到了现有的复制赋值运算符,但没有使用它。
这是我的代码(或(不是)运行 示例 here):
class foo {
public:
foo() {}
foo(foo const& r) {}
foo(foo&&) = delete;
foo const& operator=(foo const& r) { return *this; }
foo const& operator=(foo&& r) = delete;
};
int main(int argc, char **argv) {
foo bar;
bar = foo();
return 0;
}
我找到了一个非常相似的 post here.
我知道我可以通过使用临时文件来避免这种情况。我想知道为什么每个编译器(我用 gcc、clang 和 vs2013 测试过)都不能直接调用现有的复制赋值?有什么我想念的吗?
不调用复制赋值,因为(已删除的)移动赋值更适合重载解析。
根本不声明移动分配。然后将选择复制分配。不会生成隐式移动赋值运算符,因为 class 具有用户声明的复制构造函数、移动构造函数和复制赋值运算符。其中任何一个都会阻止隐式移动赋值运算符的生成。
But if i assign to an instance of this class using RVO
这里不涉及RVO。您创建一个临时 foo
并将其复制分配给现有变量。复制作业不能省略。
此外,通过赋值运算符按值 return 是非常不寻常且效率低下的。
您可以使用 placement new 来执行此操作:
#include <iostream>
#include <string>
#include <new>
class foo {
public:
foo() {}
foo(foo const& r) {}
foo(foo&&) = delete;
foo const& operator=(foo const& r) { return *this; }
foo const& operator=(foo&& r) = delete;
};
int main(int argc,char **argv)
{
foo bar;
//bar = foo();
bar.~foo();
new(&bar) foo();
return 0;
}
就像 std::move()
应用 static_cast<>()
强制使用移动 assignment/constructor 一样,可以做类似的事情来强制使用副本 assignment/constructor:
#include <iostream>
class foo
{
public:
foo() {}
foo(foo const& r) {}
foo(foo&&) = delete;
foo const& operator=(foo const& r) { std::cout << ":)\n"; return *this; }
foo const& operator=(foo&& r) = delete;
};
int main(int argc, char **argv)
{
foo bar;
bar = static_cast<const foo&>(foo());
return 0;
}
我有一个 class,其中明确删除了移动分配,因为对象不应该是可移动的。但是如果我使用 RVO 分配给这个 class 的实例,编译器会给我错误:
main.cpp:12:16: note: candidate function has been explicitly deleted
编译器也提到了现有的复制赋值运算符,但没有使用它。
这是我的代码(或(不是)运行 示例 here):
class foo {
public:
foo() {}
foo(foo const& r) {}
foo(foo&&) = delete;
foo const& operator=(foo const& r) { return *this; }
foo const& operator=(foo&& r) = delete;
};
int main(int argc, char **argv) {
foo bar;
bar = foo();
return 0;
}
我找到了一个非常相似的 post here.
我知道我可以通过使用临时文件来避免这种情况。我想知道为什么每个编译器(我用 gcc、clang 和 vs2013 测试过)都不能直接调用现有的复制赋值?有什么我想念的吗?
不调用复制赋值,因为(已删除的)移动赋值更适合重载解析。
根本不声明移动分配。然后将选择复制分配。不会生成隐式移动赋值运算符,因为 class 具有用户声明的复制构造函数、移动构造函数和复制赋值运算符。其中任何一个都会阻止隐式移动赋值运算符的生成。
But if i assign to an instance of this class using RVO
这里不涉及RVO。您创建一个临时 foo
并将其复制分配给现有变量。复制作业不能省略。
此外,通过赋值运算符按值 return 是非常不寻常且效率低下的。
您可以使用 placement new 来执行此操作:
#include <iostream>
#include <string>
#include <new>
class foo {
public:
foo() {}
foo(foo const& r) {}
foo(foo&&) = delete;
foo const& operator=(foo const& r) { return *this; }
foo const& operator=(foo&& r) = delete;
};
int main(int argc,char **argv)
{
foo bar;
//bar = foo();
bar.~foo();
new(&bar) foo();
return 0;
}
就像 std::move()
应用 static_cast<>()
强制使用移动 assignment/constructor 一样,可以做类似的事情来强制使用副本 assignment/constructor:
#include <iostream>
class foo
{
public:
foo() {}
foo(foo const& r) {}
foo(foo&&) = delete;
foo const& operator=(foo const& r) { std::cout << ":)\n"; return *this; }
foo const& operator=(foo&& r) = delete;
};
int main(int argc, char **argv)
{
foo bar;
bar = static_cast<const foo&>(foo());
return 0;
}