我试图实现自己的小型分配器用于测试目的,在设计它时我认为我不知道如何在不违反严格别名规则的情况下实现它。
在 GitHub 的大多数开源中,C++ 分配器方法allocate<T>
是内存的适配器:它运行到内存,请求N
连续的std::byte
s 或unsigned char
s,然后reinterpret_cast
将此内存分配给T
,然后将内存返回给其被调用者。
但是,这如何不违反严格的别名规则(即使被调用者必须调用构造函数本身,我们也会强制转换std::byte*
为T*
)。在实现适合大多数 STL 容器的简单缓冲区分配器时,如何解决这个问题?
7
2 个回答
2
当您假装某个内存位置存在对象但实际上并不存在时,就会违反。 (您可以通过reinterpret_cast
引用指针/引用然后取消引用它来实现这一点,其中只有引用本身才是 UB。)
它不会阻止您使用placement-new来更改某些内存中存储的对象类型,然后访问它。
例如:
#include <string>
int main()
{
alignas(std::string) char buf[sizeof(std::string)];
*reinterpret_cast<std::string*>(buf) = "foo"; // UB
std::string *ptr = new(buf) std::string;
*ptr = "foo"; // Legal.
}
2
-
在我看来,提到也可能与此相关。
– -
2@JesperJuhl 耸耸肩。它有些相关,但您可以在没有它的情况下使用分配器。
–
|
不构造任何类型T
1的对象,但是。如果您继续在指向的内存中开始 a 的生命周期,那么reinterpret_cast
avoid *
到 a就可以了。T *
T
allocate
确实启动 数组的生命周期T
,但不启动T
该数组的子对象。
|
–
–
–
–
–
|