我如何在C++中使用realloc
函数?似乎该语言缺少这个函数 - 它有new
和delete
但没有resize
!
我需要它因为我的程序读取更多数据时,需要重新分配缓冲区以存储它。我认为删除旧指针并用新的、更大的指针来进行new
操作不是正确的选择。
我如何在C++中使用realloc
函数?似乎该语言缺少这个函数 - 它有new
和delete
但没有resize
!
我需要它因为我的程序读取更多数据时,需要重新分配缓冲区以存储它。我认为删除旧指针并用新的、更大的指针来进行new
操作不是正确的选择。
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数组。
Type* t = static_cast<Type*>(malloc(n * sizeof *t));
- Ryan Hainingt.data()
而不是&t[0]
。 - knedlsepp正确的选择可能是使用可以为您完成工作的容器,例如 std::vector
。
new
和 delete
无法调整大小,因为它们只分配足以容纳给定类型对象的内存。给定类型的大小永远不会改变。虽然有 new[]
和 delete[]
,但几乎没有理由使用它们。
C 中 realloc
所做的可能只是一个 malloc
、memcpy
和 free
,尽管内存管理器允许在有足够连续的空闲内存可用时执行一些聪明的操作。
char *buf = (char *)malloc(size)
,当它变得太小时,我会执行buf = realloc(size + more_size); size += more_size
。那么如何使用vector来实现呢? - bodacydostd::vector
-需要时它会自动增长,如果需要可以预先分配内存(使用reserve()
)。 - sharptoothstd::string
也可以。 - fredoverflowthevector.resize(previous_size + incoming_size)
,然后跟着一个 memcpy
(或类似的函数)到 &thevector[previous_size]
就是你需要的。这个向量的数据保证被存储“像一个数组”。 - Thomas由于可能需要调用构造函数和析构函数,因此在C++中进行大小调整非常麻烦。
我认为,在C ++中不能有与new []
和delete []
配套使用的resize[]
操作符并不是基本原因,这个操作符可以做类似以下的事情:
newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;
显然,oldsize
将从一个秘密的位置中检索出来,就像在delete[]
中一样,并且Type
将根据操作数的类型进行选择。当类型不可复制时,resize[]
会失败,这是正确的,因为这样的对象根本无法被重定位。最后,上述代码在赋值之前默认构造对象,而实际上您不希望这样做。
如果newsize <= oldsize
,则有可能的优化是调用新缩小数组“结束后”的对象的析构函数,然后什么也不做。标准必须定义该优化是否是必需的(例如,当你resize()
一个向量时),允许但未指定,允许但依赖于具体实现,还是禁止。
您应该问自己的问题是,“提供这个功能是否真的有用,考虑到vector
已经具备了这个功能,并且专门设计为提供一个更适合C++方式的可调整大小的容器(连续内存-这个要求在C++98中省略了但在C++03中修正)?”
我认为普遍认为这个答案是“不需要”。如果您想以C方式使用可调整大小的缓冲区,请使用在C++中可用的malloc / free / realloc
。如果您想以C++方式使用可调整大小的缓冲区,请使用向量(或deque
,如果您实际上不需要连续存储)。除非您正在实现类似于向量的容器,否则不要尝试通过使用new[]
来混合两者。
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);
}
push_back()
成员函数不应直接将值分配给数组位置,因为它是一个未初始化的内存缓冲区,如果复制构造函数不是平凡的话,可能会导致未定义行为。 - LoSdelete[]
,而之前使用new[]
分配了内存,则会发生内存泄漏)。 - LoS