2

Here is my code.

DWORD *dwDSE = new DWORD[4096];

Here is my [inefficient] way of clearing it:

for (INT k=0;k<4096;k++)
    dwDSE[k] = 0;

What is the best way to clear it/initialize it to zeros?

haccks
  • 104,019
  • 25
  • 176
  • 264
JeffR
  • 765
  • 2
  • 8
  • 23
  • 3
    What makes you think that's inefficient? –  Jun 10 '14 at 09:50
  • 1
    `memset(dwDSE,0,4096);` – Jayesh Bhoi Jun 10 '14 at 09:51
  • `std::vector dwDSE (4096)` will be efficiently zeroed (or set to any other value you want). Plus, no need to `delete` it. – Baum mit Augen Jun 10 '14 at 10:03
  • possible duplicate of [C/C++ initialization of a normal array with one default value](http://stackoverflow.com/questions/1065774/c-c-initialization-of-a-normal-array-with-one-default-value) – Shmwel Jun 10 '14 at 10:09
  • @delnan, I just thought it was compared to possibly a more efficient, optimized, function. – JeffR Jun 10 '14 at 10:12
  • @JeffR The more information you give the compiler, the better it can optimize. Your loop gives maximum information, as does using `std::fill_n` or an `std::vector` (because the compiler will know the actual type involved in the loop). A function like `memset` can't do as well, because all it sees is bytes. – James Kanze Jun 10 '14 at 10:16
  • @SJD; No. That's not the dupe. – haccks Jun 10 '14 at 10:19
  • Modern LLVM will actually detect the idiom in the `for` loop and replace it with a `memset` call, as I've found before to my surprise. – slugonamission Jun 10 '14 at 15:21

4 Answers4

6

You can initialized it to zero as

DWORD *dwDSE = new DWORD[4096](); //Note the empty parenthesis ()   
haccks
  • 104,019
  • 25
  • 176
  • 264
3

Use memset:

memset(dwDSE,0,4096*sizeof(DWORD));
cegfault
  • 6,442
  • 3
  • 27
  • 49
  • Shouldn't that be `4096*sizeof(DWORD)`? You're just clearing the first 4096 bytes, not the first 4096 elements. – slugonamission Jun 10 '14 at 09:55
  • @slugonamission it is enough to say `sizeof(DWORD)` because you already set the size at declaration. See http://en.cppreference.com/w/cpp/string/byte/memset – Shmwel Jun 10 '14 at 09:57
  • @slugonamission: std::memset and memset are same? – Anil8753 Jun 10 '14 at 10:00
  • @SJD: I'm more familiar with C than C++, but I'm pretty sure `OBJ *obj = new OBJ[xxx]` is different than `OBJ obj[xxx];` That is, OP is making an array of DWORD.... – cegfault Jun 10 '14 at 10:01
  • @Anil8753 "std" a namespace. The "::" operator is the "scope" operator. It tells the compiler which class/namespace to look in for an identifier. So, `memset` is in `std` namespace. – Shmwel Jun 10 '14 at 10:02
  • @cegfault The OP is dynamically allocating an array (which you should never do in C++). You're right, however, that depending on the context, `DWORD dwDSE[4096];` might be more appropriate. – James Kanze Jun 10 '14 at 10:09
  • @SJD - that would only clear the first element, since `sizeof(DWORD)` is 4 bytes. If it was an array, `sizeof(dwDSE)` would work, but it's a simple pointer in this case. – slugonamission Jun 10 '14 at 15:19
2

Unless you've got a really bad compiler, the most efficient way of clearing it should be:

std::fill_n( dwDSI, 4096, 0 );

This should generate about the same code as your loop (which is also very efficient), and in many cases, will be significantly more efficient than memset, which is normally the worst solution (and of course, only works for the special value of 0).

Of course, you wouldn't normally ever do a new DWORD[4096] anyway. If you write:

std::vector<DWORD> dwDSI( 4096 );

you'll get it already initialized to 0, and you won't leak it in case of an exception. If you need it for a legacy interface (about the only reason one would use DWORD anyway), you can get the raw pointer with &dwDSI[0], or dwDSI.data() if you have C++11.

EDIT:

A comment to another answer makes me realize an essential point: do you really have to allocate the array dynamically? If not,

DWORD dwDSI[4096] = {};

is the best solution. (The = {} ensures initialization with 0.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • I'm using Visual Studio 2012, so is that compatible with C++11 you reference? And, if I use the vector declaration, how do I reference individual elements? – JeffR Jun 10 '14 at 10:10
  • @JeffR Partially. I think it does have the `data` member; try it, and if not, use `&dwDSI[0]`. As for referencing the individual elements: `dwDSI[index]` works perfectly; if you're referencing them sequentially, you can also use the iterators. – James Kanze Jun 10 '14 at 10:13
  • 1
    I do not want to put it on the stack, that is why I am allocating it as **new**. – JeffR Jun 10 '14 at 10:15
  • 1
    @JeffR I don't know why you wouldn't want it on the stack, but `std::vector` won't put it on the stack, so you're safe there. (In generally, you should avoid dynamic allocation whenever possible.) – James Kanze Jun 10 '14 at 10:19
  • why would I want to avoid dynamic allocation? – JeffR Jun 10 '14 at 10:37
  • @JeffR It's extra complication, and throws in a few additional things that can go wrong (like memory leaks). If one of the built-in lifetimes is appropriate, let the compiler take care of managing it. – James Kanze Jun 10 '14 at 10:41
1

The memset function can be used in this case.

std::memset(dwDSE, 0, sizeof(dwDSE)*4096);

Or fill_n function:

std::fill_n(dwDSE, 4096, 0);
Shmwel
  • 1,697
  • 5
  • 26
  • 43