如何realloc
使用C ++?这似乎是从语言缺少的-有new
和delete
,但不resize
!
我需要它,因为随着程序读取更多数据,我需要重新分配缓冲区以保存它。我认为delete
选择旧指针而new
不是新的更大指针是正确的选择。
如何realloc
使用C ++?这似乎是从语言缺少的-有new
和delete
,但不resize
!
我需要它,因为随着程序读取更多数据,我需要重新分配缓冲区以保存它。我认为delete
选择旧指针而new
不是新的更大指针是正确的选择。
Answers:
使用:: 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 ++代码,因为向量是一个智能C数组。
Type* t = static_cast<Type*>(malloc(n * sizeof *t));
t.data()
而不是&t[0]
正确的选择可能是使用一个为您完成工作的容器,例如std::vector
。
new
并且delete
无法调整大小,因为它们仅分配足够的内存来容纳给定类型的对象。给定类型的大小永远不会改变。有new[]
,delete[]
但几乎没有理由使用它们。
什么realloc
做用C很可能只是一个malloc
,memcpy
并且free
,无论如何,虽然内存管理器被允许这样做的很漂亮,如果有足够的可用连续可用内存。
std::vector
-它会在需要时自动增长,并且如果需要,您可以预分配内存reserve()
。
std::string
顺便说一句也可以。)
std::string
可以做到。顺便说一下,也有可能简化您的数据读取。您如何读取数据?
thevector.resize(previous_size + incoming_size)
,然后是memcpy
(或类似的)&thevector[previous_size]
。保证向量的数据“像数组一样”存储。
由于可能需要调用构造函数和析构函数,因此C ++中的大小调整很尴尬。
我认为,在C ++中,您无法resize[]
使用new[]
and运算符是没有根本原因的delete[]
,它做了类似的事情:
newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;
显然,oldsize
它将从一个秘密位置中检索,这与in中的相同delete[]
,并且Type
将来自操作数的类型。resize[]
在类型不可复制的地方将失败-这是正确的,因为此类对象根本无法重定位。最后,上面的代码在分配对象之前默认构造了对象,您不希望它们成为实际的行为。
有一个可能的优化方法,其中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);
}