73

How do I achieve the dynamic equivalent of this static array initialisation:

char c[2] = {};  // Sets all members to '\0';

In other words, create a dynamic array with all values initialised to the termination character:

char* c = new char[length]; // how do i amend this? 
tgh
  • 765
  • 1
  • 5
  • 7
  • 4
    Wow.. this turns out to be a great question. Lots of people unaware of std::fill_n it would seem. – Draemon Jan 08 '10 at 18:25
  • Just for the record, I'm not completely unaware of `std::fill_n`, it's just that I mostly ignore it, and only use _n algorithms when I have to. That is when the iterator type doesn't support `operator+`, and `std::advance` could be inefficient. Neither of those conditions is true of pointers. – Steve Jessop Jan 08 '10 at 18:49

10 Answers10

126
char* c = new char[length]();
Fred
  • 1,448
  • 1
  • 9
  • 4
36

Two ways:

char *c = new char[length];
std::fill(c, c + length, INITIAL_VALUE);
// just this once, since it's char, you could use memset

Or:

std::vector<char> c(length, INITIAL_VALUE);

In my second way, the default second parameter is 0 already, so in your case it's unnecessary:

std::vector<char> c(length);

[Edit: go vote for Fred's answer, char* c = new char[length]();]

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
22

Maybe use std::fill_n()?

char* c = new char[length];
std::fill_n(c,length,0);
mrkj
  • 3,041
  • 19
  • 24
20

The array form of new-expression accepts only one form of initializer: an empty (). This, BTW, has the same effect as the empty {} in your non-dynamic initialization.


The above applies to pre-C++11 language. Starting from C++11 one can use uniform initialization syntax with array new-expressions

char* c = new char[length]{};
char* d = new char[length]{ 'a', 'b', 'c' };
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
7

Since c++11 we could use list initialization:

char* c = new char[length]{};

For an aggregate type, then aggregate initialization will be performed, which has the same effect like char c[2] = {};.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
5

C++ has no specific feature to do that. However, if you use a std::vector instead of an array (as you probably should do) then you can specify a value to initialise the vector with.

std::vector <char> v( 100, 42 );

creates a vector of size 100 with all values initialised to 42.

4

You can't do it in one line easily. You can do:

char* c = new char[length];
memset(c, 0, length);

Or, you can overload the new operator:

void *operator new(size_t size, bool nullify)
{
    void *buf = malloc(size);

    if (!buf) {
             // Handle this
    }

    memset(buf, '\0', size);

    return buf;
}

Then you will be able to do:

char* c = new(true) char[length];

while

char* c = new char[length];

will maintain the old behavior. (Note, if you want all news to zero out what they create, you can do it by using the same above but taking out the bool nullify part).

Do note that if you choose the second path you should overload the standard new operator (the one without the bool) and the delete operator too. This is because here you're using malloc(), and the standard says that malloc() + delete operations are undefined. So you have to overload delete to use free(), and the normal new to use malloc().

In practice though all implementations use malloc()/free() themselves internally, so even if you don't do it most likely you won't run into any problems (except language lawyers yelling at you)

Andreas Bonini
  • 44,018
  • 30
  • 122
  • 156
  • But... You can see std::fill / std::fill_n – Jasper Bekkers Jan 08 '10 at 18:16
  • The goggles...they do nothing – Draemon Jan 08 '10 at 18:24
  • Probably because this is a strange way to approach the problem. The more canonical solutions are to use `fill_n` (`memset` is raw, `fill_n` is more generic, and to be consistent you would use it), a `vector`, or the shortcut-to-0 answer above. That said, your `operator new` could have a few improvements. Instead of malloc just use the regular `operator new`: `buf = ::operator new(size)`. That should automatically take care of all exceptions for you, and `new_handlers`. (Assuming the global `operator new` does that correctly) – GManNickG Jan 08 '10 at 21:25
1

No internal means, AFAIK. Use this: memset(c, 0, length);

szedjani
  • 550
  • 2
  • 6
  • 21
Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
1

and the implicit comment by many posters => Dont use arrays, use vectors. All of the benefits of arrays with none of the downsides. PLus you get lots of other goodies

If you dont know STL, read Josuttis The C++ standard library and meyers effective STL

pm100
  • 48,078
  • 23
  • 82
  • 145
0

you have to initialize it "by hand" :

char* c = new char[length];
for(int i = 0;i<length;i++)
    c[i]='\0';
almathie
  • 731
  • 5
  • 22