18

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?

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
neuviemeporte
  • 6,310
  • 10
  • 49
  • 78
  • What are you objecting to? The necessity of writing code to initialize a vector? The time it takes to copy? Note that any compiler trickery to initialize a dynamically allocated array would involve the same copying, since it's not possible to guarantee that the allocated memory comes with the exact right contents. – David Thornley Sep 21 '10 at 14:38
  • If performance is of the essence, why are you dynamically allocating at all? Why the indirection through a pointer? As you are "statically initializing" the array anyway, surely the dimensions of the matrices are known at compile time? – fredoverflow Sep 21 '10 at 14:41
  • I'm not objecting to anything, just asking. I'm using a matrix class of my own which stores data in a dynamically-allocated array and I thought it nice if I could initialize that array without copying the data manually. :) – neuviemeporte Sep 21 '10 at 14:41
  • @Fred: this is just a test case for the matrix to see if it gives me correct results for certain predefined inputs. In the general case, the size is not known at compile time. – neuviemeporte Sep 21 '10 at 14:43
  • 1
    Okay, so you are probably working with very large matrices? In that case, there may be better data structures than arrays or vectors depending on the nature of those matrices. – fredoverflow Sep 21 '10 at 14:48

6 Answers6

31

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
  • 256,549
  • 94
  • 388
  • 662
  • 5
    `+1` for `std::vector`. What reason is there to still use your own dynamic arrays? – sbi Sep 21 '10 at 14:21
  • @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 Sep 21 '10 at 14:24
  • @sbi - accessing native array elements is faster than doing the same with a vector. Tested. – Poni Sep 21 '10 at 14:27
  • 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 Sep 21 '10 at 14:29
  • 6
    @neu: If you don't even trust `std::vector`, maybe you should ditch C++ altogether and go for assembly language. – fredoverflow Sep 21 '10 at 14:31
  • 6
    @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 Sep 21 '10 at 14:34
  • @FredOverflow: I think may be @neuviemeporte's comment needs to be addressed specifically on inlining part. Your comment does not help – Chubsdad Sep 21 '10 at 14:36
  • @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 Sep 21 '10 at 14:44
  • 2
    @neuviemeporte: Which accessor functions? If you feel you absolutely need to keep control, you can always write something like `int * ptr = &v[0];` 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 Sep 21 '10 at 14:46
  • @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 Sep 21 '10 at 14:48
  • @David Thornley: But how do you take care of dynamic growth and related invalidation? – Chubsdad Sep 21 '10 at 14:49
  • @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 Sep 21 '10 at 14:58
  • @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 Sep 21 '10 at 14:59
  • 3
    @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 Sep 21 '10 at 15:08
  • 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 Sep 22 '10 at 07:58
  • 1
    @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 Sep 22 '10 at 09:55
  • 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 Sep 22 '10 at 16:45
  • @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 Sep 24 '10 at 07:32
  • @Poni: I successfully use `std::vector` 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 Sep 24 '10 at 07:35
  • @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 Sep 24 '10 at 13:37
  • 1
    @Poni: [Arrays and vectors (can) generate the same asm.](http://www.xs4all.nl/~weegen/eelis/vector-speed.cpp) –  Sep 25 '10 at 12:49
  • @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 Sep 26 '10 at 12:08
  • 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 Sep 28 '10 at 18:27
  • Does this line really works? `int* p = new int[3] { 1, 2, 3 };` I tried it, it is always giving me a compilation error. – user3437460 Jun 04 '16 at 11:22
  • @user3437460 What compiler are you using, and what is the error message? [ideone](https://ideone.com/nT4eX3) accepts the code... – fredoverflow Jun 04 '16 at 13:24
  • @fredoverflow Thanks for your reply. I tried it with Quincy 2005 and Dev-C++. The error msg is `expected ',' or ';' before '{' token` – user3437460 Jun 04 '16 at 20:43
  • @user3437460 You can enable C++11 support in Dev-C++ according to [this](http://stackoverflow.com/questions/16951376) question... but I have no personal experience with either of the IDEs you mentioned. – fredoverflow Jun 04 '16 at 20:51
12

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)

Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
Chubsdad
  • 24,777
  • 4
  • 73
  • 129
4

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
  • 12,825
  • 5
  • 58
  • 90
1

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
  • 12,414
  • 18
  • 67
  • 93
1

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
  • 12,345
  • 5
  • 44
  • 76
  • 3
    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 Sep 21 '10 at 14:33
  • +1 Although this is a little cryptic and only works for PODs. – fredoverflow Sep 21 '10 at 14:33
  • 1
    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 Sep 21 '10 at 14:36
  • 2
    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 Sep 21 '10 at 14:40
  • @James: Unfortunately, there are people out there willing to sacrifice every good software principle for the holy cow of "performance". – fredoverflow Sep 21 '10 at 14:51
-1

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
  • 11,061
  • 25
  • 80
  • 121