How do you 'realloc' in C++?

2020-01-24 11:58发布

问题:

How can I realloc in C++? It seems to be missing from the language - there is new and delete but not resize!

I need it because as my program reads more data, I need to reallocate the buffer to hold it. I don't think deleteing the old pointer and newing a new, bigger one, is the right option.

回答1:

Use ::std::vector!

Type* t = (Type*)malloc(sizeof(Type)*n) 
memset(t, 0, sizeof(Type)*m)

becomes

::std::vector<Type> t(n, 0);

Then

t = (Type*)realloc(t, sizeof(Type) * n2);

becomes

t.resize(n2);

If you want to pass pointer into function, instead of

Foo(t)

use

Foo(&t[0])

It is absolutely correct C++ code, because vector is a smart C-array.



回答2:

The right option is probably to use a container that does the work for you, like std::vector.

new and delete cannot resize, because they allocate just enough memory to hold an object of the given type. The size of a given type will never change. There are new[] and delete[] but there's hardly ever a reason to use them.

What realloc does in C is likely to be just a malloc, memcpy and free, anyway, although memory managers are allowed to do something clever if there is enough contiguous free memory available.



回答3:

Resizing in C++ is awkward because of the potential need to call constructors and destructors.

I don't think there's a fundamental reason why in C++ you couldn't have a resize[] operator to go with new[] and delete[], that did something similar to this:

newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;

Obviously oldsize would be retrieved from a secret location, same is it is in delete[], and Type would come from the type of the operand. resize[] would fail where the Type is not copyable - which is correct, since such objects simply cannot be relocated. Finally, the above code default-constructs the objects before assigning them, which you would not want as the actual behaviour.

There's a possible optimisation where newsize <= oldsize, to call destructors for the objects "past the end" of the newly-ensmallened array and do nothing else. The standard would have to define whether this optimisation is required (as when you resize() a vector), permitted but unspecified, permitted but implementation-dependent, or forbidden.

The question you should then ask yourself is, "is it actually useful to provide this, given that vector also does it, and is designed specifically to provide a resize-able container (of contiguous memory--that requirement omitted in C++98 but fixed in C++03) that's a better fit than arrays with the C++ ways of doing things?"

I think the answer is widely thought to be "no". If you want to do resizeable buffers the C way, use malloc / free / realloc, which are available in C++. If you want to do resizeable buffers the C++ way, use a vector (or deque, if you don't actually need contiguous storage). Don't try to mix the two by using new[] for raw buffers, unless you're implementing a vector-like container.



回答4:

try something like that:

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

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

    // Board DataBoard[255];
    int SelectedBoard;

} RUNDATA;

Vector will complain. That's why arrays, malloc and new still exists.