c++ - 实现标记 union 的移动构造函数

标签 c++ c++11 unions move-constructor

我使用包含匿名 union 和标记的类实现了标记 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_;
    };
};

我在实现移动构造函数时遇到了问题。在重载的“普通”构造函数中,我知道要初始化哪个 union 成员:

LogFile::LogFile(std::ofstream fileStream)
: streamType_(FILE_STREAM), fileStream_(std::move(fileStream))
{
}

但是在 move 构造函数中,我怎么知道我必须初始化 stdStream_fileStream_ 中的哪一个。我无法在初始化列表中检查 streamType_ 的值。

最佳答案

除非您是为了练习,否则请将标记的 union 替换为 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 更好的原因。

关于c++ - 实现标记 union 的移动构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50115132/

相关文章:

c++ - C++11 中的内存排序与主内存刷新排序有关吗?

c++ - 振奋 spirit 2 : is there a way to know what is the parser progression percentage?

c++ - QT - 多选

c++ - 这个 C++ 代码在技术上会发生什么?

c++ - 分配 Union 的字段

c++ - 什么是空类的大小以及 C++ 中 union 、结构和类之间的区别?

c++ - 我应该删除 C++ 中的静态对象吗?

c++ - 为什么 std::move 会阻止 RVO(返回值优化)?

c++ - std::array<T, N> 的大小是否保证等于 T[N] 的大小?

c - 在指向结构的指针上打印错误值