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]似乎表明它应该是这种情况.
根据我的观察,默认分配器的库实现似乎与此类似,并且无需担心!是不是真的安全投这样?
我们如何确定两个指针是相同的,还是我们可以?
我很惊讶没人提到这个便宜的反例:
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)
但是,除非调用特定于类的放置版本,否则您的断言应该成立.两个表达式必须表示与另一个答案中解释的相同的地址(主要的一点是标准的非分配operator new只返回指针参数而新表达式没有做任何花哨的事情),这些都不是指针超过结束某些对象所以,通过[expr.eq]/2,他们比较相等.