实现标记联合的移动构造函数
Implementing a move constructor of a tagged union
我使用包含匿名联合和标记的类实现了一个标记联合:
class LogFile
{
public:
LogFile(std::ostream& stdStream);
LogFile(std::ofstream fileStream);
LogFile(LogFile&& logFile);
~LogFile();
std::ostream& getStream();
private:
enum { STD_STREAM, FILE_STREAM } streamType_;
union
{
std::ostream *stdStream_;
std::ofstream fileStream_;
};
};
我在实现移动构造函数时遇到问题。在重载的"正常"构造函数中,我知道要初始化哪个联盟成员:
LogFile::LogFile(std::ofstream fileStream)
: streamType_(FILE_STREAM), fileStream_(std::move(fileStream))
{
}
但是在移动构造函数中,我怎么知道我必须初始化哪个stdStream_
或fileStream_
。我无法在初始值设定项列表中检查streamType_
的值。
除非您这样做是为了练习,否则请将标记的联合替换为 std::variant
。它更安全。
以后可以使用 placement-new 有条件地调用它,而不是在成员初始值设定项列表中调用构造函数。
通常,如果未在成员初始值设定项列表中指定构造函数,则会调用默认构造函数。但是对于union {...};
的成员,根本没有调用构造函数。
LogFile(LogFile&& other) : streamType_(other.streamType_)
{
switch (streamType_)
{
case FILE_STREAM:
new (&fileStream_) std::ofstream(std::move(other.fileStream_)); // <--
break;
case STD_STREAM:
stdStream_ = other.stdStream_;
other.stdStream_ = 0;
break;
}
}
请注意,您必须在 ~LogFile()
中手动调用析构函数,并且还需要自定义移动赋值。这就是为什么std::variant
更好。
相关文章:
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 运算符+ 的规范实现涉及额外的移动构造函数
- C ++为什么在移动构造函数中需要移动/前进
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 为什么这里不调用移动构造函数?
- 隐式移动构造函数
- 如何为具有私有成员的派生类实现移动构造函数
- 为什么不调用移动构造函数
- 是否可以避免在以下代码中复制/移动构造函数的需要?