代码之家  ›  专栏  ›  技术社区  ›  Curious

什么时候可以安全地在不清洗的情况下重新使用一个微不足道的可毁坏对象的内存?

  •  1
  • Curious  · 技术社区  · 5 年前

    关于以下代码:

    class One { 
    public:
      double number{};
    };
    
    class Two {
    public:
      int integer{};
    }
    
    class Mixture {
    public:
      double& foo() {
        new (&storage) One{1.0};
        return reinterpret_cast<One*>(&storage)->number;
      }
    
      int& bar() {
        new (&storage) Two{2};
        return reinterpret_cast<Two*>(&storage)->integer;
      }
    
      std::aligned_storage_t<8> storage;
    };
    
    int main() {
      auto mixture = Mixture{};
      cout << mixture.foo() << endl;
      cout << mixture.bar() << endl;
    }
    

    我没有为这些类型调用析构函数,因为它们是可破坏的。我对标准的理解是,为了安全起见,在将指针传递给 reinterpret_cast . 但是,libstdc++中std::optional的实现似乎没有使用 std::launder() 只需将对象直接构造到联合存储中。 https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/optional .

    我上面的例子是定义明确的行为吗?我需要做什么才能让它工作?一个工会能使这个工作吗?

    1 回复  |  直到 5 年前
        1
  •  1
  •   Brian Bi    5 年前

    std::launder reinterpret_cast

    reinterpret_cast<One*>(&storage)
    

    static_cast<One*>(static_cast<void*>(&storage))
    

    static_cast One

    T

    storage

    aligned_storage

    union {
        One one;
        Two two;
    };
    

    Two const

    std::optional CWG 1776 N4303 P0137

    推荐文章