根据reinterpret_cast creating a trivially default-constructible object,具有简单默认构造函数的对象无法通过简单地重新解释适当对齐的存储来创建[],因此需要new放置。这应该同样适用于std::realloc。是cppreference example中的static_cast:

#include <cstdlib>
class MallocDynamicBuffer
{
    char* p;
public:
    void resize(std::size_t newSize) {
        if(void* mem = std::realloc(p, newSize)) {
            p = static_cast<char*>(mem);
        }
    }
};

错误的,因为它不会创建有效的对象?

将包含static_cast的行替换为p = new(mem) T[newSize]T=char或任何其他易于复制和易于构建的类型是否正确?我不确定,因为这将要求对先前构建和移动的数据调用new放置是有效的。调用一个平凡可构造类型的构造函数可以保证该值保持不变且不确定。

最佳答案

实际答案:如果trivially copyable types不允许使用realloc(也就是说,所有复制和移动构造函数和赋值运算符都是琐碎的,至少有一个复制或移动构造函数或赋值运算符,而析构函数是琐碎的),这似乎是标准中的错误我无法想象编译器编写器会在此处引起问题。

语言律师回答:我认为除charunsigned charstd::byte之外的任何其他类型的标准都不允许这样做,而且我不再像评论该问题时那样确定那些类型(如果realloc创建了一些基础对象,则很好,但是没有)。这些函数are specified可以“具有C标准库中指定的语义”,这并不是特别有用,因为C的语义不等同于C++“对象”的概念。对malloc的一般理解是,它不会创建C++对象,因此您需要自己通过放置new来实现;我认为realloc也会发生同样的情况。

您建议的在new[]的结果上使用位置realloc的解决方案也不起作用。由于new[]需要跟踪分配的元素数(供delete[]使用),因此it is allowed添加了一些开销空间,然后在其收到的指针之后返回了一个指针,因此第一部分就是开销。尽管对于new[]放置不是必需的,但是it is still allowed(这使我认为根本没有使用new[]放置的有效方法,因为您不知道会请求多少开销,因此无法确保您有足够的空间为了它)。

即使您确保只使用非数组放置new(我可以想到仍然可以解决realloc的几个变通办法),它的确会在那里创建一个有效的对象(对于trivial default constructors的类型,至少允许它不起作用默认初始化时),但可能具有indeterminate value。现在,在我看来,它可能有效,但标准有些含糊,但that is debatable和我可能是错的。

关于c++ - std::restatic与static_cast或放置新,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51344271/

10-11 22:53
查看更多