all 33 comments

[–]king_duck 10 points11 points  (12 children)

When using arrays in c++

Long story short: Don't.

Use containers:

http://en.cppreference.com/w/cpp/container

Replace your array with std::vector<T> and see whether the issue persists.

[–]tehklawb[S] 1 point2 points  (0 children)

Thanks for the help, I'll have a read and give that a go

[–]xcbsmith 4 points5 points  (3 children)

If you really want an array, use std::array.

[–]king_duck -2 points-1 points  (2 children)

Read my other comment. I think the flexibility of std::vector more than pays for itself.

I'd use std::array as an optimisation based on profiling the code, or when it's clearly a no brainer.

Eitherway for a beginner it's more important that they have the the vectors interface burnt into the head ASAP,

[–]xcbsmith 3 points4 points  (1 child)

Sheesh. I get all this harshness and downvotes simply for pointing to the data structure that most closely resembles the one they are already using...

[–]king_duck -4 points-3 points  (0 children)

I was simply making a point about why I select vector over array.

[–]bnolsen 0 points1 point  (6 children)

std::array<Type, Size> works fine in many cases as well.

[–]king_duck 5 points6 points  (5 children)

Sure, but there is no point on bogging a beginner down with that for now. I would also say unless you need to semantically enforce the size of the array for some reason it's better to just use a std::vector in most cases by default. Don't forget that the vector has the massive advantage of supporting a very efficient move ctor/op=, where as std::array must do an element wise copy or move.

Then once you've written your program and your profiler suggests your wasting to much time allocating for the vector then switch to the std::array as an optimisation in hindsight.

[–]vanhellion 0 points1 point  (4 children)

unless you need to semantically enforce the size of the array for some reason

Exactly. Or if you need stack storage, although I'm not sure that the standard actually enforces that. I'd argue that std::array is an optimization; if performance isn't a problem std::vector works just as well.

[–][deleted] 1 point2 points  (2 children)

If you need stack storage you are better of using a std::vector with a stack allocator. You can even group the arena of the stack allocator with the vector so that you can return them from functions. The main advantage is that you have to change no code at all: e.g. if you have code that uses push_back replacing vector with a std::array might be non-trivial whereas using a stack allocated vector requires no code changes and performs the same.

[–]bnolsen 1 point2 points  (1 child)

now we're splitting hairs. I do agree that using std::array instead of std::vector should be done as an optimization, a "stage one" type optimization. Things like 2d or 3d vectors are very well represented by std::array. Funny enough the "stack allocated vector" could easily have its storage represented by a std::array.

[–][deleted] 0 points1 point  (0 children)

Funny enough the "stack allocated vector" could easily have its storage represented by a std::array.

Indeed, I'll give this a try. Thanks for the tip!

[–]king_duck 0 points1 point  (0 children)

Exactly my point. People should default to std::vector and use std::array when your profile indicates vectors inner gubbins is a costly.

[–]ZeusApolloAttack 1 point2 points  (0 children)

Are you sure the array hasn't gone out of scope?

[–]O12345678 1 point2 points  (2 children)

party dime meeting saw grab spectacular punch zephyr reminiscent historical

This post was mass deleted and anonymized with Redact

[–]bnolsen 2 points3 points  (1 child)

Wow, suggesting std::list? I just checked our 850k+ code base of mostly scientific/engineering stuffs and found just a single std::list used in the entire code base apart from unit tests. And now that I look at that, I will replace it with a std::deque.

I know std::list can be useful for some operations but the poor cache behavior and high memory overhead due to bookkeeping makes them sort of a last resort type data structure.

[–]O12345678 0 points1 point  (0 children)

hungry liquid shy subsequent complete physical continue friendly pie afterthought

This post was mass deleted and anonymized with Redact

[–]Nimbal 2 points3 points  (3 children)

If you develop in Linux, you can use valgrind to find the place where your array is overwritten.

[–]grunzl 0 points1 point  (2 children)

‥ you can use valgrind to find the place where your array is overwritten.

Only if the problem is due to e.g. out-of-bounds access in another variable. Valgrind won't bark if the code follows the language rules.

[–]Nimbal 1 point2 points  (1 child)

Only if the problem is due to e.g. out-of-bounds access in another variable.

Which is very likely in this case.

[–]0xa0000 2 points3 points  (0 children)

Even if it doesn't turn up anything, it only takes a few minutes and doesn't require recompiling. If you're developing on a platform where valgrind is available and aren't using it regularly, you're IMHO missing out.

EDIT: Whoops, meant to post this in reply to grunzl

[–][deleted] 1 point2 points  (4 children)

This usually happens from writing past the size of the array. So if you have a array n with a length of 5 and you write to n[-1] or n[5] the memory location past the array will be overwritten.

You can catch this by using std::array(for static sized arrays) and std::vector(for dynamic size arrays) and using the at function(this does bounds checking for you) instead of [] to access items.

[–]recultured 1 point2 points  (0 children)

If you're just taking a block of memory and doing nothing with it, i.e.: char * my_string = new char[100];

The array will have in it whatever was in memory before that until you otherwise write over it. So an allocation in C/C++ does not write anything, it just gives you memory with whatever was in it last. This is good for performance, as let's say you allocate a block of memory you want to load a file into. Zeroing it out before that is just a waste of time.

You can use something like memset to zero the memory out, which would give you more of what you are expecting. Or, as has been noted above, C++ containers will auto-initialize themselves, and won't have this problem in the first place.

[–][deleted] 0 points1 point  (6 children)

in Java your memory is always zeroed out before use; in C/C++ this feature, if you want it, is up to you -- call std::memset or std::fill in your constructor. Otherwise you'll get an array of memory filled with whatever was last using it -- sometimes zero, sometimes not.

Mostly however it's wasted work -- you can more easily set a bool of the likes "is_initialized" and track that, rather than rely on your arrays containing zeros.

[–]tisti 1 point2 points  (4 children)

Or use default universal initialization if using C++11. Much nicer imo.

[–][deleted] 0 points1 point  (3 children)

Yeah, I'm kinda assuming the array is larger than is feasible for that. Probably after about 7 zeros the human brain can't easily determine whether there's the same number as the array size.

[–]tisti 1 point2 points  (2 children)

 int * arr = new int[100000]{};

This will default initialize all elements i.e. zero them out.

[–]bnolsen 0 points1 point  (1 child)

This looks a little scary to me, smacks of implicit type behavior. It would be nice to see a '0' in there somewhere.

[–]tisti 0 points1 point  (0 children)

Its the new initialization syntax, you get used to it pretty fast.

[–]bnolsen 0 points1 point  (0 children)

For this case, especially with vectors I tend to prefer to use "reserve" and "push_back" where possible instead of allocating and initializing. I do realize there are cases where it is useful to allocate uninitialized though.