【发布时间】:2015-02-12 11:32:44
【问题描述】:
我不是在寻找type trait for movable types,也不是rules for automatic generation of move operations。我正在寻找的是一个通用指南,以了解是否要移动或复制给定类型,或者通过测试自己确定它的方法。
在某些情况下,移动操作是在用户没有注意到的情况下执行的,例如:
void f(std::string) { ... }
void f_c(const std::string) { ... }
void g()
{
f(std::string("Hello world!")); // moved, isn't it?
f("Hello world!"); // moved, isn't it?
f_c(std::string("Hello world!")); // moved, isn't it?
f_c("Hello world!"); // moved, isn't it?
}
在 C++11 之前,上面的代码会在 std::string 中从一个临时值复制到传递给 f 和 f_c 的值,从 C++11 开始,std::basic_string 提供了一个移动构造函数(见here (8))并且临时创建的被移动到传递给f和f_c的参数中。
有时用户试图使用std::move 函数强制移动语义:
std::string return_by_value_1()
{
std::string result("result);
return std::move(result); // Is this moved or not?
}
std::string return_by_value_2()
{
return std::move(std::string("result)); // Is this moved or not?
}
但是std::move 不移动任何东西1:它只将左值转换为右值引用,如果目标类型没有实现移动语义:不执行移动操作......和 AFAIK上面return_by_value_x 函数中的std::moveing 会阻止编译器执行RVO(我们正在恶化代码!)。
所以,在(可能是不必要的)介绍之后,我会问我的问题:
如何知道或测试给定类型是否会被移动或复制?
这个问题是关于基本类型和复杂类型的:
int f_int(int) { ... };
template <typename F, typename S> void f_pair(std::pair<F, S>) { ... };
struct weird
{
int i;
float f;
std::vector<double> vd;
using complexmap = std::map<std::pair<std::string, std::uint64_t>, std::pair<std::uint32_t, std::uint32_t>>;
complexmap cm;
};
struct silly
{
std::vector<std::pair<const std::string, weird::complexmap>> vcm;
};
f_weird(weird) { ... };
f_silly(silly) { ... };
- 基本类型可以移动吗?有一些对
f_int的调用,这意味着移动操作?f_int(1); // this moves or construct an int in-place?f_int(1 + 2); // this moves or construct an int in-place?f_int(f_int(1) + 2); // this moves or construct an int in-place?
- 不能移动具有 const 成员的 complex 类型,不是吗?
f_pair<std::pair<const std::string, int>>({"1", 2}); // unmovable?f_pair<std::pair<std::string, std::string>>({"1", "2"}); // this moves?f_silly({{{}, {}}}); // this moves?
-
struct weird可以移动吗?f_weird({1, .0f, {0.d, 1.d}, {{{"a", 0ull}, {1u, 2u}}}}) // this moves?
- 如何自行测试上述情况以确定给定类型是否在给定上下文中移动?
1如果叫std::rvalref或者类似的名字会不会更好?
【问题讨论】:
-
...你知道
f和f_c的签名是完全一样的吗? -
这似乎是一个大约 25 部分的问题。你能每个问题问一个问题吗?
-
我认为这里没有真正的问题。
-
也许不能通过右值构造?
-
@LightnessRacesinOrbit 也许你是对的,在我看来所有的问题都是一样的(所有的问题都是关于移动语义的)但也许每个部分都值得一个单独的问题,这就是你建议?
标签: c++ c++11 move-semantics