我正在创建一个受歧视的类工会。我正在使用 c++ 17,所以我可以在技术上使用 a std::variant
,但是由于特定的用例,我希望每个变体的含义更加明确(特别是因为其中两个案例除了它们是哪种情况外没有数据)。该类看起来像这样(为了简单起见,我将忽略问题中的移动语义):
class MyC {
public:
enum class Kind {A, B, C, D};
private:
Kind _kind;
union {
struct {} _noVal;
string _aVal;
int _bVal;
};
MyC(Kind kind) : _kind(kind), _noVal() {}
public:
MyC(const MyC& other) : _kind(other.kind), _noVal() {
if (_kind == Kind::A) new (&_aVal) string(other._aVal);
if (_kind == Kind::B) _bVal = other._bVal;
}
~MyC() {
if (_kind == Kind::A) _aVal.~string();
}
MyC& operator =(const MyC&);
// factory methods and methods for consuming the current value
}
我对复制赋值运算符的第一个想法是
MyC& MyC::operator &(const MyC& other) {
this->~MyC();
_kind = other._kind;
if (_kind == Kind::A) new (&_aVal) string(other.aVal);
else if (_kind == Kind::B) _bVal = other.bVal;
else _noVal = other.noVal;
return *this;
}
这对我来说似乎很好,但我想知道调用字符串的复制赋值运算符是否更好的 C++ 风格,这需要更像这样的东西:
MyC& MyC::operator &(const MyC& other) {
if (other._kind == Kind::A) {
if (_kind != Kind::A) new (&_aVal) string; // *
_aVal = other.aVal;
} else if (other._kind == Kind::B) {
_bVal = other.bVal;
} else {
_noVal = other.noVal;
}
_kind = other._kind;
return *this;
}
总而言之,这样做的正确方法是什么(以及为什么),或者这很重要?
* 这行是因为我的原始实现aVal
直接设置而没有确保那里曾经初始化过一个字符串,并且它崩溃了。