考虑以下几点。
struct T { int a = 1; };
struct U { char b = 2; };
static_assert(alignof(U) == 1);
// Allocate storage. Cast via P0593 to access implicit array of unsigned char.
auto* s = reinterpret_cast<unsigned char*>(::operator new(sizeof(T) + sizeof(U)));
// Place T and U in that storage.
T* t = new (s) T;
U* u = new (s + sizeof(T)) U;
// Is there a legal way to get a pointer to `u` given only `t` and not `s`?
U* u2 = reinterpret_cast<U*>(reinterpret_cast<unsigned char*>(t) + sizeof(T));
问:有没有一种方法,只给t
得到u
?
我知道我可以用std::launder()
s
得到t
,我大概可以用std::launder()
s + sizeof(T)
得到u
。但是,如果我只有t
,有办法吗?
我知道std::launder()
有关于“可达性”的要求,所以我不认为它可以成为解决方案的一部分,因为t
无法从t
访问u
。
我知道,如果我把T和U放在一个结构体中,事情就不同了,但这不是我感兴趣的情况。(考虑到U实际上可能是动态大小。)
我想我的问题可以归结为:如何从t
恢复s
(底层 * 完整 * 存储)?我知道我可以得到t
处的对象的对象表示,但我不认为这和s
是一样的,因为它只有sizeof(T)
长,对吧?
如果我想分配一次并存储这些非数组的不同对象,我是否必须在t
中存储指向u
的指针,以便稍后恢复它?
1条答案
按热度按时间ckocjqey1#
正如你所说,
std::launder
有一个先决条件,明确禁止这一点。这似乎是不可能的。在语言中还有一些其他的结构可以使更多的字节达到比这个前提条件应该是可能的,见例如。我的问题std::launder vs placement-new reachability condition和Does implicit object creation circumvent reachability conditions of std::launder?。
然而,考虑到这些限制被显式地添加到
std::launder
中,我怀疑它们没有被应用到这些其他结构中是缺陷,而不是相反。我不知道是否有任何编译器实际上利用这种可达性限制进行优化。