根据here编写的内容,new
在免费商店中分配,而malloc
使用堆,这两个术语通常意味着同样的事情。
根据here编写的内容,realloc
可能会将内存块移动到新位置。如果free store和heap是两个不同的内存空间,那么它是否意味着任何问题呢?
具体来说,我想知道使用是否安全
int* data = new int[3];
// ...
int* mydata = (int*)realloc(data,6*sizeof(int));
如果没有,是否有任何其他方式可以安全地分配realloc
new
内存?我可以分配新区域和memcpy
内容,但据我所知,realloc
可能会使用相同的区域。
答案 0 :(得分:46)
您只能realloc
通过malloc
(或家人,如calloc
)分配的内容。
这是因为跟踪内存空闲和使用区域的底层数据结构可能完全不同。
可能是,但绝不保证C ++ new
和C malloc
使用相同的底层分配器,在这种情况下realloc
可以同时适用于这两者。但正式的是在UB-land。而在实践中,它只是不必要的风险。
C ++不提供与realloc
对应的功能。
最接近的是std::vector
等容器(内部缓冲区)的自动重新分配。
C ++容器的设计方式不允许使用realloc
。
而不是提供的代码
int* data = new int[3];
//...
int* mydata = (int*)realloc(data,6*sizeof(int));
......这样做:
vector<int> data( 3 );
//...
data.resize( 6 );
但是,如果您绝对需要realloc
的一般效率,并且如果您必须接受new
原始分配,那么您对效率的唯一追索是使用特定于编译器的方法,知识使用此编译器realloc
是安全的。
否则,如果您绝对需要realloc
的一般效率,但不是被迫接受new
,那么您可以使用malloc
和realloc
。使用智能指针可以让您获得与C ++容器相同的安全性。
答案 1 :(得分:16)
C ++添加到realloc
的唯一可能相关限制是C ++的malloc
/ calloc
/ realloc
不得以::operator new
的形式实现,其free
不得以::operator delete
的形式实现(根据C ++ 14 [c.malloc] p3-4)。
这意味着您正在寻找的保证在C ++中不存在。但是,这也意味着您可以::operator new
实施malloc
。如果你这样做,那么从理论上讲,::operator new
的结果可以传递给realloc
。
在实践中,您应该关注new
的结果与::operator new
的结果不匹配的可能性。 C ++编译器可以是例如合并多个new
表达式以使用单个::operator new
调用。这是编译器在标准不允许的情况下已经做过的事情,IIRC,标准现在允许它(根据C ++ 14 [expr.new] p10)。这意味着即使你走这条路,你仍然无法保证将new
指针传递给realloc
做任何有意义的事情,即使它不再是未定义的行为。
答案 2 :(得分:8)
一般来说,不要这样做。如果您正在使用带有非平凡初始化的用户定义类型,则在重新分配 - 复制释放的情况下,{{1}将不会调用对象的析构函数 }}。复制时,副本构造函数也不会被调用。由于对象生存期的使用不正确,这可能导致未定义的行为(请参阅 C ++标准§3.8对象生存期,[basic.life] )。
1对象的生命周期是对象的运行时属性。如果一个对象属于类或聚合类型,并且它或其成员之一由除了普通默认构造函数之外的构造函数初始化,则称该对象具有非平凡的初始化。 [注意:通过简单的复制/移动构造函数进行初始化是非平凡的初始化。 - 后注]
T类对象的生命周期始于:
- 获得具有类型T的正确对齐和大小的存储,并且
- 如果对象具有非平凡的初始化,则其初始化完成。
类型T的对象的生命周期在以下时间结束:
- 如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用开始,或
- 重用或释放对象占用的存储空间。
后来(强调我的):
3本国际标准中归属于对象的属性仅适用于给定对象仅在其生命周期。
所以,你真的不想在其生命周期内使用 。
答案 3 :(得分:5)
这不安全,而且不优雅。
有可能覆盖new / delete以支持重新分配,但您也可以考虑使用容器。
答案 4 :(得分:4)
是 - 如果"
实际上首先调用了new
(例如,这就是VC ++ malloc
的工作方式)。
否则。请注意,一旦您决定重新分配内存(因为new
称为new
),您的代码将特定于编译器,并且不再在编译器之间移植。
(我知道这个答案可能会让很多开发人员感到不安,但我的回答取决于真实的事实,而不仅仅是惯用语。)
答案 5 :(得分:4)
这不安全。首先,您传递给realloc
的指针必须是从malloc
或realloc
:http://en.cppreference.com/w/cpp/memory/c/realloc获得的。
其次new int [3]
的结果不必与分配函数的结果相同 - 可以分配额外的空间来存储元素的数量。
(对于比int
更复杂的类型,realloc
不安全,因为它不会调用复制或移动构造函数。)
答案 6 :(得分:3)
你可能(不是在所有情况下),但你不应该。如果您需要调整数据表的大小,则应使用std::vector
代替。
有关如何使用它的详细信息列在另一个SO question。
中答案 7 :(得分:3)
一般来说,没有。
为确保安全,必须坚持下去:
琐碎的类型满足上述要求。
另外:
new[]
- 函数必须将请求传递给malloc
而不做任何更改,也不要进行任何记账。您可以通过替换global new []和delete []或相应类中的那些来强制执行此操作。答案 8 :(得分:-1)
这些功能主要用于C。
memset将内存块中的字节设置为特定值。
malloc分配一块内存。
calloc,与malloc相同。唯一的区别是它将字节初始化为零。
在C ++中,分配内存的首选方法是使用new。
C:int intArray =(int *)malloc(10 * sizeof(int)); C ++:int intArray = new int [10];
C:int intArray =(int *)calloc(10 * sizeof(int)); C ++:int intArray = new int10;