我怎样才能realloc
在 C++ 中?语言中似乎缺少它 - 有new
但delete
没有resize
!
我需要它,因为当我的程序读取更多数据时,我需要重新分配缓冲区来保存它。我不认为delete
ing 旧指针和new
ing 一个新的、更大的指针是正确的选择。
我怎样才能realloc
在 C++ 中?语言中似乎缺少它 - 有new
但delete
没有resize
!
我需要它,因为当我的程序读取更多数据时,我需要重新分配缓冲区来保存它。我不认为delete
ing 旧指针和new
ing 一个新的、更大的指针是正确的选择。
使用 ::std::vector!
Type* t = (Type*)malloc(sizeof(Type)*n)
memset(t, 0, sizeof(Type)*m)
变成
::std::vector<Type> t(n, 0);
然后
t = (Type*)realloc(t, sizeof(Type) * n2);
变成
t.resize(n2);
如果要将指针传递给函数,而不是
Foo(t)
采用
Foo(&t[0])
这是绝对正确的 C++ 代码,因为 vector 是一个智能 C 数组。
正确的选择可能是使用为您完成工作的容器,例如std::vector
.
new
并且delete
无法调整大小,因为它们分配的内存刚好足以容纳给定类型的对象。给定类型的大小永远不会改变。有new[]
,delete[]
但几乎没有理由使用它们。
无论如何,C中realloc
的作用可能只是一个malloc
,memcpy
和free
,尽管如果有足够的连续空闲内存可用,内存管理器可以做一些聪明的事情。
由于可能需要调用构造函数和析构函数,因此在 C++ 中调整大小很尴尬。
resize[]
我不认为在 C++ 中你不能有一个操作符与new[]
and一起使用的根本原因delete[]
,它做了类似这样的事情:
newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;
显然oldsize
会从一个秘密位置检索,它在 中也是如此delete[]
,并且Type
来自操作数的类型。resize[]
在 Type 不可复制的情况下会失败 - 这是正确的,因为这些对象根本无法重新定位。最后,上面的代码在分配对象之前默认构造对象,这是您不希望的实际行为。
有一个可能的优化newsize <= oldsize
,在新缩小的数组的“结束”之后调用对象的析构函数,并且什么都不做。标准必须定义是否需要这种优化(就像当你resize()
使用向量时一样),允许但未指定,允许但依赖于实现,或禁止。
然后你应该问自己的问题是,“提供这个真的有用吗,因为它vector
也这样做,并且专门设计用于提供一个可调整大小的容器(连续内存——C++98 中省略了这个要求,但是已在 C++03 中修复),这比使用 C++ 做事方式的数组更合适?”
我认为答案被广泛认为是“不”。如果您想以 C 方式进行可调整大小的缓冲区,请使用malloc / free / realloc
C++ 中可用的 。如果您想以 C++ 方式进行可调整大小的缓冲区,请使用向量(或者deque
,如果您实际上不需要连续存储)。不要尝试通过使用new[]
原始缓冲区来混合两者,除非您正在实现类似矢量的容器。
这是一个 std::move 示例,它使用 realloc 实现了一个简单的向量(每次达到限制时*2)。如果有比我下面的副本做得更好的方法,请告诉我。
编译为:
g++ -std=c++2a -O2 -Wall -pedantic foo.cpp
代码:
#include <iostream>
#include <algorithm>
template<class T> class MyVector {
private:
T *data;
size_t maxlen;
size_t currlen;
public:
MyVector<T> () : data (nullptr), maxlen(0), currlen(0) { }
MyVector<T> (int maxlen) : data (new T [maxlen]), maxlen(maxlen), currlen(0) { }
MyVector<T> (const MyVector& o) {
std::cout << "copy ctor called" << std::endl;
data = new T [o.maxlen];
maxlen = o.maxlen;
currlen = o.currlen;
std::copy(o.data, o.data + o.maxlen, data);
}
MyVector<T> (const MyVector<T>&& o) {
std::cout << "move ctor called" << std::endl;
data = o.data;
maxlen = o.maxlen;
currlen = o.currlen;
}
void push_back (const T& i) {
if (currlen >= maxlen) {
maxlen *= 2;
auto newdata = new T [maxlen];
std::copy(data, data + currlen, newdata);
if (data) {
delete[] data;
}
data = newdata;
}
data[currlen++] = i;
}
friend std::ostream& operator<<(std::ostream &os, const MyVector<T>& o) {
auto s = o.data;
auto e = o.data + o.currlen;;
while (s < e) {
os << "[" << *s << "]";
s++;
}
return os;
}
};
int main() {
auto c = new MyVector<int>(1);
c->push_back(10);
c->push_back(11);
}