Dan*_*son 7 c++ unions move-constructor c++11
有没有更好的方法为类似联合的类构建移动构造函数?如果我在下面的代码中有类似类的类似类的类,有没有办法构建类或移动构造函数,它不需要像下面代码中的移动构造函数那样的switch语句.
class S {
private:
enum {CHAR, INT, DOUBLE} type; // tag
// anonymous union
union {
char c;
int n;
double d;
};
public:
// constructor if the union were to hold a character
AS(const char c) {
this->tag = AS::CHAR;
this->c = c;
}
// constructor if the union were to hold a int
AS(const int i) {
this->tag = AS::INT;
this->n = i;
}
// constructor if the union were to hold a double
AS(const double d) {
this->tag = AS::DOUBLE;
this->d = d;
}
// Move constructor with switch statement
S(S &&src) : type(std::move(src.type)) {
switch(type) {
case CHAR:
this->c = src.c);
src.c = 0;
break;
case INT:
this->n = src.n;
src.n = 0;
break;
case DOUBLE:
this->d = src.d;
src.d = 0
break;
default:
break;
}
}
};
Run Code Online (Sandbox Code Playgroud)
不,没有更好的方法。如果要安全地从包含任意类型的联合中移动,则必须从最后写入的联合的字段(如果有)中进行。另一个相反的答案是错误的,考虑一个例子
union SomethingLikeThisIsGoingToHappenInPractice {
std::string what_we_actually_want_to_move;
char what_we_do_not_care_about[sizeof(std::string)+1];
};
Run Code Online (Sandbox Code Playgroud)
如果在这里使用“最大”类型的移动构造函数,则必须在char此处选择数组,尽管移动实际上并没有做任何事情。如果std::string设置了该字段,您希望移动其内部缓冲区,如果您查看char数组,则不会发生这种情况。还要记住,移动语义是关于语义的,而不是关于移动内存的。如果这是您可以始终使用memmove并完成的问题,则不需要 C++11。
这甚至不涉及从您尚未编写为 C++ UB 的联合成员读取的问题,即使对于原始类型,尤其是对于类类型。
TL; DR 如果您发现自己处于这种情况,请使用 OP 最初提出的解决方案,而不是已接受的答案中的解决方案。
PS:当然,如果你只是移动一个只包含微不足道可移动的东西的联合,比如原始类型,你可以只使用默认的移动构造函数来复制内存;在这种情况下,除了为了一致性之外,首先拥有移动构造函数真的不值得。
CLL*_*CLL -1
由于联合作为一种数据类型,对于内部的所有字段引用内存中的同一位置(尽管该空间内较小字段(例如 4 字节的 char 数组 [4])的顺序取决于系统),因此可以只使用最大的字段移动并集。这将确保您每次都移动整个联合,无论您当前正在将联合用于哪些字段。
class S {
private:
enum {CHAR, INT, DOUBLE} type; // tag
// anonymous union
union {
char c;
int n;
double d;
};
public:
// Move constructor with switch statement
S(S &&src) : type(std::move(src.type)) {
this->d = src.d;
src.d = 0;
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1297 次 |
| 最近记录: |