放置新的返回值

god*_*sti 27 c++ language-lawyer c++14

考虑以下C++ 14代码:

#include <cassert>
#include <new>
#include <type_traits>

struct NonStandardLayout
{
    // ...
};

int main()
{
    using T = NonStandardLayout;

    std::aligned_storage_t< sizeof(T), alignof(T) > storage;
    T *const valid_ptr = new(static_cast<void *>(&storage)) T;

    T *const maybe_ptr = reinterpret_cast<T *>(&storage);
    assert(maybe_ptr == valid_ptr); // ???

    valid_ptr->T::~T();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

对于任何类型的T,标准是否保证示例中的断言永远不会失败?

讨论

看看最新的标准(http://eel.is/c++draft/),我看不到任何对这个特定场景的引用,但我发现以下段落可以说是答案'是'.

我认为[expr.new/15]和[new.delete.placement/2]一起表明其值valid_ptr将等于地址storage总是吗?

如果是这样,是否reinterpret_cast会产生指向完全构造对象的指针?因为,[expr.reinterpret.cast/7],[expr.static.cast/13]和[basic.compound/4]似乎表明它应该是这种情况.

根据我的观察,默认分配器的库实现似乎与此类似,并且无需担心!是不是真的安全投这样?

我们如何确定两个指针是相同的,还是我们可以?

Col*_*mbo 5

我很惊讶没人提到这个便宜的反例:

struct foo {
  static foo f;
  // might seem dubious but doesn't violate anything
  void* operator new(size_t, void* p) {return &f;}
};
Run Code Online (Sandbox Code Playgroud)

Coliru演示.

但是,除非调用特定于类的放置版本,否则您的断言应该成立.两个表达式必须表示与另一个答案中解释的相同的地址(主要的一点是标准的非分配operator new只返回指针参数而新表达式没有做任何花哨的事情),这些都不是指针超过结束某些对象所以,通过[expr.eq]/2,他们比较相等.