Initialize a Vector to Zeros C++/C++11

initialize a vector to zeros C++/C++11

You don't need initialization lists for that:

std::vector<int> vector1(length, 0);
std::vector<double> vector2(length, 0.0);

how can we initialize a vector with all values 0 in C++

You can use:

std::vector<int> v(100); // 100 is the number of elements.
// The elements are initialized with zero values.

You can be explicit about the zero values by using:

std::vector<int> v(100, 0);

You can use the second form to initialize all the elements to something other than zero.

std::vector<int> v(100, 5); // Creates object with 100 elements.
// Each of the elements is initialized to 5

efficient way to initialize a vector with zero after constructor

I think this method couldn't be efficient.

Well, you can just use the constructor

 std::vector<int> var(100000000,0);

or the resize() function

 var.resize(100000000,0);

I'd suspect these are implemented as efficient as can be, while doing yourself using push_back() may have some unwanted side effects.

Why does c++ initialise a std::vector with zeros, but not a std::array?

Suppose we have some class:

class MyClass {
int value;

public:
MyClass() {
value = 42;
}
// other code
};

std::vector<MyClass> arr(10); will default construct 10 copies of MyClass, all with value = 42.

But suppose it didn't default construct the 10 copies. Now if I wrote arr[0].some_function(), there's a problem: MyClass's constructor has not yet run, so the invariants of the class aren't set up. I might have assumed in the implementation of some_function() that value == 42, but since the constructor hasn't run, value has some indeterminate value. This would be a bug.

That's why in C++, there's a concept of object lifetimes. The object doesn't exist before the constructor is called, and it ceases to exist after the destructor is called. std::vector<MyClass> arr(10); calls the default constructor on every element so that all the objects exist.

It's important to note that std::array is somewhat special, since it is initialized following the rules of aggregate initialization. This means that std::array<MyClass, 10> arr; also default constructs 10 copies of MyClass all with value = 42. However, for non-class types such as unsigned, the values will be indeterminate.


There is a way to avoid calling all the default constructors: std::vector::reserve. If I were to write:

std::vector<MyClass> arr;
arr.reserve(10);

The vector would allocate its backing array to hold 10 MyClasss, and it won't call the default constructors. But now I can't write arr[0] or arr[5]; those would be out-of-bounds access into arr (arr.size() is still 0, even though the backing array has more elements). To initialize the values, I'd have to call push_back or emplace_back:

arr.push_back(MyClass{});

This is often the right approach. For example, if I wanted to fill arr with random values from std::rand, I can use std::generate_n along with std::back_inserter:

std::vector<unsigned> arr;
arr.reserve(10);
std::generate_n(std::back_inserter(arr), 10, std::rand);

It's also worth noting that if I already have the values I want for arr in a container, I can just pass the begin()/end() in with the constructor:

std::vector<unsigned> arr{values.begin(), values.end()};

Initializing a two dimensional std::vector

Use the std::vector::vector(count, value) constructor that accepts an initial size and a default value:

std::vector<std::vector<int> > fog(
ROW_COUNT,
std::vector<int>(COLUMN_COUNT)); // Defaults to zero initial value

If a value other than zero, say 4 for example, was required to be the default then:

std::vector<std::vector<int> > fog(
ROW_COUNT,
std::vector<int>(COLUMN_COUNT, 4));

I should also mention uniform initialization was introduced in C++11, which permits the initialization of vector, and other containers, using {}:

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

Initialize vector to zero

This line:

perm(charLength, 0);

Does not call the constructor std::vector(size_t, const T&) and initialize the vector with 160 elements of value 10. In fact, I don't see how that compiled at all since the vector class doesn't have an operator().

std::vector contains a member function assign() that you can instead:

perm.assign(charLength, 0);

Value-Initialized Objects in C++11 and std::vector constructor

Question: Is my understanding correct here? Does explicit vector::vector(size_type count) provide an uninitialized array
(similar to malloc) if T is a POD?

No. There is a difference here between C++03 and C++11, but that isn't it. The difference is that in C++03, vector<T>(N) would default construct a T, and then make N copies of it to populate the vector.

Whereas in C++11, vector<T>(N) will populate the vector by default constructing T N times. For POD types the effect is identical. Indeed, I would expect that for almost all types the effect is identical. However for something like a unique_ptr (a move-only type), the difference is critical. The C++03 semantics would never work since you can not make a copy of a move-only type.

So:

vector<unique_ptr<int>> v(10);

creates a vector of 10 null unique_ptrs (which are not copies of each other).

In the rare case that it makes a difference and you need the C++03 behavior that can easily be accomplished with:

vector<T> v(10, T());

C++: how to initialize vector in map with non-zero size

Use map::try_emplace() (or map::emplace() before C++17)

std::vector has a constructor which takes an initial size and an initial uniform value. In your case, suppose you want 125 as the initial size. With a stand-alone vector, you would use:

size_t num_bools_we_want = 1234;
std::vector<bool> my_vec(num_bools_we_want, false);

Now, std::map has a method named map::try_emplace() which forwards arguments to a constructor of the value type, which effectively allows you to choose the constructor it will use for a new element. Here's how to use it

mymap.try_emplace(42, num_bools_we_want, false);

to create a value of std::vector<bool>(num_bools_we_want, false) for the key 42. No temporary vectors are created (regardless of compiler optimizations).

The only "problem" with this solution is that try_emplace() only exists since C++17. Since you asked about C++11 - that version of the standard introduced map::emplace(), which does almost the same thing except for an issue with making a copy of the key. See this question for a discussion of the difference between emplace() and try_emplace().

What is the easiest way to initialize a std::vector with hardcoded elements?

One method would be to use the array to initialize the vector

static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

C++11 vector of vectors initialization

For a combination of reasons, uniform initialization is kind of broken for std::vector<int> (and more generally, vector of arithmetic type). Uniform initialization uses the same syntax as list-initialization (constructing from initializer_list); when the syntax is ambiguous, the constructor taking initializer_list takes precedence.

Thus, std::vector<int> v(42); means "use std::vector(size_t) constructor to create a vector of 42 zeros"; while std::vector<int> v{42}; means "use std::vector(std::initializer_list) constructor to create a vector with a single element having value 42".

Similarly, std::vector<int> v(5, 10); uses two-parameter constructor to create a vector of 5 elements, all with value 10; while std::vector<int> v{5, 10}; uses initializer_list-taking constructor and creates a vector of two elements, values 5 and 10.



Related Topics



Leave a reply



Submit