Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在分配内存空间后重用内存空间_C++_Memory Management - Fatal编程技术网

C++ 在分配内存空间后重用内存空间

C++ 在分配内存空间后重用内存空间,c++,memory-management,C++,Memory Management,这个程序是不是格式错误 #include <new> struct A { int a; int b; }; struct B { int a; }; int main() { void* p(operator new(sizeof(A))); new (p) A(); static_cast<A*>(p)->~A(); new (p) B(); static_cast<B*>(p)->~B();

这个程序是不是格式错误

#include <new>

struct A
{
  int a;
  int b;
};

struct B
{
  int a;
};

int main()
{    
  void* p(operator new(sizeof(A)));
  new (p) A();
  static_cast<A*>(p)->~A();

  new (p) B();
  static_cast<B*>(p)->~B();

  operator delete(p);
}
#包括
结构A
{
INTA;
int b;
};
结构B
{
INTA;
};
int main()
{    
void*p(新操作符(sizeof(A));
新(p)A();
静态_cast(p)->~A();
新的(p)B();
静态_cast(p)->~B();
运算符删除(p);
}
请注意,我们保证
p
类型将正确对齐
a
。但是类型
B
?标准中有提到什么吗?是否有标准的方法重新对齐
p


编辑:我觉得被接受的答案需要更多的解释
operator new
必须返回与该大小的任何对象正确对齐的指针,但该对象将是什么类型的?它不知道(对齐方式取决于类型),因此它必须为所有可能类型的实例提供一个正确对齐的指针,因为“较小”类型的最大对齐方式小于“较大”类型,指针应该正确对齐。

如果在sizeof表达式中使用a和B的并集,只有纯粹主义者会抱怨。像这样:

union AllocObject {
    A a;
    B b;
};

main() {
    char* p = new char[sizeof AllocObject];
    ...
}

但是,如果您关注<代码>新< /COD>性能,您应该考虑自己这样执行全局分配运算符:

void* operator new (size_t size) {
    void* result = malloc(size);
    if(!result) throw(bad_alloc());    //Just for standard conformance, unnecessary on Linux...
    return result;
}

void operator delete (void *pointer) {
    free(pointer);
}
当然,您可能会做得更好,但即使是上面的代码也比我机器上的内置版本快100个CPU周期


<>请注意,在C++文件中有这样一个链接到程序中,当程序使用<代码> new < /C>运算符时,它会被自动调用。

< p>标准说明<代码>运算符new <代码>的结果应该适合所有类型。但是,这不包括扩展对齐类型,如SSE类型。

不是格式错误,因为您知道p处的内存位置可以适合B,但肯定是奇数。我见过类层次结构的容器实现,这些类层次结构分配了一个由n个插槽组成的数组,每个插槽都是该数组可能容纳的最大类。在此之后,placement new可用于防止任何进一步的内存分配/间接寻址,即使容器在技术上包含不同的类型。@Aggieboy当然可以,但对齐问题如何?我不确定这一点,但如果您将
B
的定义修改为
struct alignas(A)B{…}应该没问题。我不认为像其他评论所支持的那样格式错误。不过,这可能是不明智的。除非你非常小心,否则很快你就会忘记那块内存当前包含一个
A
,你试着把它当作一个
B
…因为A和B都有int类型的成员,所以对齐是可以的。如果您希望此操作适用于用户定义的A&B(如模板参数),则对齐将是一个问题。运算符new必须在失败时抛出,因此这不是符合标准的代码。@MikeVine:是的,可能必须这样做,您可以轻松添加它。我会相应地修改答案。你为什么不抛出bad\u alloc()
?我也不会抱怨,只要你不尝试使用
p
而不是
char
array.-1因为
sizeof
这样的联合对任何人都没有帮助,它必须是
sizeof
alignof
,而且是为了展示一个没有解释的轶事是的,这是相当令人费解的地方,标准实现放松了100个周期。。。有趣的是,因为
operator new
malloc
的定义完全是为了相同的目的…效果:由新表达式(5.3.4)调用的分配函数(3.7.4.1),用于分配适当对齐的存储大小字节,以表示该大小的任何对象。如果所需的大小小于以前提供的大小,该怎么办?@user1095108:该类型的对齐方式永远不能超过较大大小的最大对齐方式,因此它必须有效。标准在哪里说,该对齐方式(较小的类型)@user1095108:没有,因为这不是真的,但也不是我说的。任何类型T的最大允许校准标准为
sizeof(T)
。因此,最大
alignof(较小的类型)
如果我理解正确,那么
alignof(较小的类型)
可能仍然大于
alignof(较大的类型)
,指针可能仍然需要重新对齐到正确的对齐方式。