您如何在C ++中“重新分配”?


85

如何realloc使用C ++?这似乎是从语言缺少的-有newdelete,但不resize

我需要它,因为随着程序读取更多数据,我需要重新分配缓冲区以保存它。我认为delete选择旧指针而new不是新的更大指针是正确的选择。


8
Stroustrup很久以前就回答了这个问题,请参见:www2.research.att.com/~bs/bs_faq2.html#renew(如果您是C ++的新手,以及Cline的C ++ FAQ,那将是一个很好的开始)
令人发指的是,2010年

8
@dirkgently引用的答案现在位于:stroustrup.com/bs_faq2.html#renew-Cline的FAQ现在是超级FAQ的一部分:isocpp.org/faq
maxschlepzig 2015年

Answers:


54

使用:: 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数组。


1
memset行不应该是memset(t,0,sizeof(T)* n);吗?n而不是m?
拉斐尔·梅耶

1
@anthom是的。真的应该是Type* t = static_cast<Type*>(malloc(n * sizeof *t));
Ryan Haining

2
对于C ++ 11,现在将使用t.data()而不是&t[0]
knedlsepp 2015年

1
然后如何删除它?
a3mlord

@ a3mlord:你什么意思?让它超出范围,它就消失了。
Lightness Races in Orbit

51

正确的选择可能是使用一个为您完成工作的容器,例如std::vector

new并且delete无法调整大小,因为它们仅分配足够的内存来容纳给定类型的对象。给定类型的大小永远不会改变。有new[]delete[]但几乎没有理由使用它们。

什么realloc做用C很可能只是一个mallocmemcpy并且free,无论如何,虽然内存管理器被允许这样做的很漂亮,如果有足够的可用连续可用内存。


6
@bodacydo:不要实现增长的缓冲区,只需使用std::vector-它会在需要时自动增长,并且如果需要,您可以预分配内存reserve()
Sharptooth

4
使用std :: vector <T>。这就是它的目的。在C ++中,除非您明确编写资源管理类,否则没有理由自己使用new / delete / new [] / delete []。
小狗

4
@bod:是的,可以。(std::string顺便说一句也可以。)
fredoverflow

1
是的,可以,没问题。甚至std::string可以做到。顺便说一下,也有可能简化您的数据读取。您如何读取数据?
托马斯

2
所需的听起来像是thevector.resize(previous_size + incoming_size),然后是memcpy(或类似的)&thevector[previous_size]。保证向量的数据“像数组一样”存储。
托马斯

36

由于可能需要调用构造函数和析构函数,因此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 / reallocC ++中可用的。如果要以C ++方式进行可调整大小的缓冲区,请使用向量(或deque,如果实际上不需要连续存储,则使用)。new[]除非您要实现类似矢量的容器,否则不要尝试通过使用原始缓冲区来混合两者。


0

这是一个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);
}

-7

尝试这样的事情:

typedef struct Board
{
    string name;
    int size = 0;
};

typedef struct tagRDATA
{
    vector <Board> myBoards(255);

    // Board DataBoard[255];
    int SelectedBoard;

} RUNDATA;

矢量会抱怨。这就是为什么数组,malloc和new仍然存在的原因。


12
不,那不是为什么。而且我看不出它如何以任何方式回答问题。还是为什么要typedef像在写C一样在各处使用?
轨道上的竞速赛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.