views:

250

answers:

6

In C++, I can statically initialize an array, e.g.:

int a[] = { 1, 2, 3 };

Is there an easy way to initialize a dynamically-allocated array to a set of immediate values?

int *p = new int[3];
p = { 1, 2, 3 }; // syntax error

...or do I absolutely have to copy these values manually?

+1  A: 

No, you cannot initialize a dynamically created array in the same way.

Most of the time you'll find yourself using dynamic allocation in situations where static initialization doesn't really make sense anyway. Such as when you have arrays containing thousands of items. So this isn't usually a big deal.

Daniel Bingham
+7  A: 

You have to assign each element of the dynamic array explicitly (e.g. in a for or while loop)

However the syntax int *p = new int [3](); does initialize all elements to 0 (value initialization $8.5/5)

Chubsdad
+19  A: 

You can in C++0x:

int* p = new int[3] { 1, 2, 3 };
...
delete[] p;

But I like vectors better:

std::vector<int> v { 1, 2, 3 };

If you don't have a C++0x compiler, boost can help you:

#include <boost/assign/list_of.hpp>
using boost::assign::list_of;

vector<int> v = list_of(1)(2)(3);
FredOverflow
`+1` for `std::vector`. What reason is there to still use your own dynamic arrays?
sbi
@sbi Agreed, it doesn't seem like there's a whole lot of use in rolling your own when vectors are so much nicer.
EricBoersma
@sbi - accessing native array elements is faster than doing the same with a vector. Tested.
Poni
Maybe vectors are nicer, but I don't trust their implementation. I need to have extra-fast matrices so I wrap them in a struct with an exposed pointer to the data aligned in an array - this will also allow me to use SSE intrinsics. I avoid the overhead of calling accessor functions, which either are or aren't inlined - I could never tell.
neuviemeporte
@neu: If you don't even trust `std::vector`, maybe you should ditch C++ altogether and go for assembly language.
FredOverflow
@Poni: There is no necessary reason why accessing a vector would be detectably slower than accessing an array, so any test that claims otherwise applies to a certain compiler, compiler options, and libraries only. Bear in mind that an implementation can do additional checks, and many do when in debug mode, or when certain compiler options are selected.
David Thornley
@FredOverflow: I think may be @neuviemeporte's comment needs to be addressed specifically on inlining part. Your comment does not help
Chubsdad
@Chub: Well, member functions that are defined inside the class definition [are always inlined](http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.8), and in every implementation that I poked around, the member functions of `std::vector` were defined inside the class definition. You pretty much have to do this with class templates anyway, right?
FredOverflow
@neuviemeporte: Which accessor functions? If you feel you absolutely need to keep control, you can always write something like `int * ptr = ` and `...ptr[i]...`, since (as of 2003) vector contents storage is guaranteed to be contiguous. Just make sure to change `ptr` any time the vector size increases.
David Thornley
@Fred: are you sure defining a function in a class makes it actually inlined, or does it only give it an implicit inline directive, which the compiler can ignore at will, as usual?
neuviemeporte
@David Thornley: But how do you take care of dynamic growth and related invalidation?
Chubsdad
@neuv: No, I am not sure. Whenever I *need* to be sure, I look at the generated assembly code **with optimizations turned to the maximum level**.
FredOverflow
@Chubsdad: I got the impression there was no dynamic growth, but if I'm wrong that is one more thing to take care of when adding to the vector size and/or capacity. On the other hand, it's probably no worse than doing the `realloc` check every time for a C-style array.
David Thornley
@Poni: We have had this argument before on SO and it is **NOT** true. See here. (http://stackoverflow.com/questions/3664272/3664349#3664349) where we show conclusively that there is no difference between vector and built-in array.
Martin York
To all those who don't agree with me about the fact that vector is slower than native array in accessing elements terms - I've tested it so many times trying to optimize a certain loop... using Release build, optimized for speed, under vc++ 2008, 32bit app. Argue or not, I know what I'm saying, at least about this very tiny issue. In order to maximize access speed in a vector I make a pointer to its internal array and directly access it. No at(), nor operator[] or any other crappy method that slows down things for this reason or another.
Poni
@Poni: Have you tried `#define _SECURE_SCL 0`? Otherwise, you'll get bounds checks every time you access a vector via `operator[]`, even in release builds.
FredOverflow
Yes Fred - believe me I did some decent investigation at that time (2-3 months ago), and this one issue - none can argue with me. If I ever find the time I'll post an "Answer" here on SO that shows it, and you guys will be able to "Question" it as much as you want (:
Poni
Martin's code, at the link he posted, deals with totally different thing than what I'm saying, which again is: *accessing* vector elements is slower. Not talking about assigning or anything else.
Poni
@FredOverflow: "...member functions that are defined inside the class definition are always inlined,..." That's an unfortunate wording. These functions are inline functions but they are not always inlined. In fact, a compiler doesn't have to be able to inline anything. Of course, making a function an inline function makes inlining easier.
sellibitze
@Poni: I successfully use `std::vector<double,Alloc>` with a custom allocator for SSE compatible alignment (wrapper around fftw_malloc). So, data is alined and I get to access it via raw pointers. What else do you want?
sellibitze
@sellibitze : What else do **I want**? haha! Only that you have a good day. I can't even remember how I started talking here - leave me alone people! HAHA!
Poni
@Poni: [Arrays and vectors (can) generate the same asm.](http://www.xs4all.nl/~weegen/eelis/vector-speed.cpp)
Roger Pate
@Poni: What you claim goes against everything ever found out about `std::vector` -- and that's some pretty big names against you. Unless you back up what you're saying with a piece of code, the platform, and exact compiler settings, what you say is not credible. However, _even if what you claim turns out to be true_ (which I doubt until proven otherwise), this one case of profiling would not warrant not using `std::vector` in general. Profiling code often makes it grow ugly warts in the 10% of it that are performance-relevant. But that doesn't mean we should write warty code all the time.
sbi
I perfectly understand your guys opinion here and why it sounds like I'm saying something which is wrong - well - I'm gonna leave that for another day!
Poni
A: 

Never heard of such thing possible, that would be nice to have.

Keep in mind that by initializing the array in the code that way

int a[] = { 1, 2, 3 };

..... only gains you easier code writing and NOT performance. After all, the CPU will do the work of assigning values to the array, either way you do it.

Poni
A: 

Using helper variable:

const int p_data[] = {1, 2, 3};
int* p = (int*)memcpy(new int[3], p_data, sizeof(p_data));

or, one line

int p_data[] = {1, 2, 3},  *p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
Abyx
As a general rule (and a good habit to get into), you should not dynamically allocate an object in a function call (that is, you should never call `new` in an argument to a function). The reason is that the order of evaluation of function arguments is unspecified, so you could end up dynamically allocating the memory, then the evaluation of another argument might throw an exception, then that dynamically allocated object will be leaked. [Herb Sutter has more](http://www.gotw.ca/gotw/056.htm).
James McNellis
+1 Although this is a little cryptic and only works for PODs.
FredOverflow
James McNellis, general rules are just _general_ rules. And them have an explanations, to ensure that rule matches the case. In this case, all is OK.
Abyx
@Abyx: In _this particular case_, yes, it is "ok;" but writing high-quality code means writing code to well-known, safe patterns (especially when the pattern does not impose any overhead). This code wouldn't get past any reasonably critical code review (or, at least it shouldn't).
James McNellis
@James: Unfortunately, there are people out there willing to sacrifice every good software principle for the holy cow of "performance".
FredOverflow
+4  A: 

To avoid endless push_backs, I usually initialize a tr1::array and create a std::vector (or any other container std container) out of the result;

const std::tr1::array<T, 6> values = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(values.begin(), values.end());

The only annoyance here is that you have to provide the number of values explicitly.

This can of course be done without using a tr1::array aswell;

const T values[] = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(&values[0], &values[sizeof(values)/sizeof(values[0])]);

Althrough you dont have to provide the number of elements explicitly, I prefer the first version.

Viktor Sehr
+1 Neat solution!
FredOverflow