Initializing the size of a C++ vector
There are a few ways of creating a vector
with n
elements and I will even show some ways of populating a vector when you don't know the number of elements in advance.
But first
what NOT to do
std::vector<Entry> phone_book;
for (std::size_t i = 0; i < n; ++i)
{
phone_book[i] = entry; // <-- !! Undefined Behaviour !!
}
The default constructed vector, as in the example above creates an empty vector. Accessing elements outside of the range of the vector is Undefined Behavior. And don't expect to get a nice exception. Undefined behavior means anything can happen: the program might crash or might seem to work or might work in a wonky way. Please note that using reserve
doesn't change the actual size of the vector, i.e. you can't access elements outside of the size of the vector, even if you reserved for them.
And now some options analyzed
default ctor + push_back
(suboptimal)
std::vector<Entry> phone_book;
for (std::size_t i = 0; i < n; ++i)
{
phone_book.push_back(entry);
}
This has the disadvantage that reallocations will occur as you push back elements. This means memory allocation, elements move (or copy if they are non-movable, or for pre c++11) and memory deallocation (with object destruction). This will most likely happen more than once for an n
decently big. It is worth noting that it is guaranteed "amortized constant" for push_back
which means that it won't do reallocations after each push_back
. Each reallocation will increase the size geometrically. Further read: std::vector and std::string reallocation strategy
Use this when you don't know the size in advance and you don't even have an estimate for the size.
"count default-inserted instances of T" ctor with later assignments (not recommended)
std::vector<Entry> phone_book(n);
for (auto& elem : phone_book)
{
elem = entry;
}
This does not incur any reallocation, but all n
elements will be initially default constructed, and then copied for each push. This is a big disadvantage and the effect on the performance will most likely be measurable. (this is less noticeable for basic types).
Don't use this as there are better alternatives for pretty much every scenario.
"count copies of elements" ctor (recommended)
std::vector<Entry> phone_book(n, entry);
This is the best method to use. As you provide all the information needed in the constructor, it will make the most efficient allocation + assignment. This has the potential to result in branchless code, with vectorized instructions for assignments if Entry
has a trivial copy constructor.
default ctor + reserve
+ push_back
(situational recommended)
vector<Entry> phone_book;
phone_book.reserve(m);
while (some_condition)
{
phone_book.push_back(entry);
}
// optional
phone_book.shrink_to_fit();
No reallocation will occur and the objects will be constructed only once until you exceed the reserved capacity. A better choice for push_back
can be emplace_back
.
Use this If you have a rough approximation of the size.
There is no magical formula for the reserve value. Test with different values for your particular scenarios to get the best performance for your application. At the end you can use shrink_to_fit
.
default ctor + std::fill_n
and std::back_inserter
(situational recommended)
#include <algorithm>
#include <iterator>
std::vector<Entry> phone_book;
// at a later time
// phone_book could be non-empty at this time
std::fill_n(std::back_inserter(phone_book), n, entry);
Use this if you need to fill or add elements to the vector after its creation.
default ctor + std::generate_n
and std::back_inserter
(for different entry
objects)
Entry entry_generator();
std::vector<Entry> phone_book;
std::generate_n(std::back_inserter(phone_book), n, [] { return entry_generator(); });
You can use this if every entry
is different and obtained from a generator
Intializer list (Bonus)
Since this has become such a big answer, beyond of what the question asked, I will be remised if I didn't mention the initializer list constructor:
std::vector<Entry> phone_book{entry0, entry1, entry2, entry3};
In most scenarios this should be the default go-to constructor when you have a small list of initial values for populating the vector.
Some resources:
std::vector::vector
(constructor)
std::vector::insert
standard algorithm library (with std::generate
std::generate_n
std::fill
std::fill_n
etc.)
std::back_inserter
How to initialize std::vector from C-style array?
Don't forget that you can treat pointers as iterators:
w_.assign(w, w + len);
How to initialize a vector in C++
With the new C++ standard (may need special flags to be enabled on your compiler) you can simply do:
std::vector<int> v { 34,23 };
// or
// std::vector<int> v = { 34,23 };
Or even:
std::vector<int> v(2);
v = { 34,23 };
On compilers that don't support this feature (initializer lists) yet you can emulate this with an array:
int vv[2] = { 12,43 };
std::vector<int> v(&vv[0], &vv[0]+2);
Or, for the case of assignment to an existing vector:
int vv[2] = { 12,43 };
v.assign(&vv[0], &vv[0]+2);
Like James Kanze suggested, it's more robust to have functions that give you the beginning and end of an array:
template <typename T, size_t N>
T* begin(T(&arr)[N]) { return &arr[0]; }
template <typename T, size_t N>
T* end(T(&arr)[N]) { return &arr[0]+N; }
And then you can do this without having to repeat the size all over:
int vv[] = { 12,43 };
std::vector<int> v(begin(vv), end(vv));
C++ vector set size in initialization list or resize
The latter will generally first default-construct the vector, then reallocate the vector's storage to accommodate the new length (if larger than the default) (see here for assembly code). In contrast, there will be only one allocation for the first variant (less assembly code).
Note that compiler optimizations may well see through this, but there is another reason (other than avoiding premature pessimization) to prefer the first: By explicitly initializing all members in the constructor initialization list (or inline), you can have tooling that informs you when you leave something uninitialized by accident.
how-to initialize 'const std::vectorT' like a c array
For C++11:
vector<int> luggage_combo = { 1, 2, 3, 4, 5 };
Original answer:
You would either have to wait for C++0x or use something like Boost.Assign to do that.
e.g.:
#include <boost/assign/std/vector.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope
vector<int> v;
v += 1,2,3,4,5;
initialize an vector with a specified number of unitialized space
The problem is that you are creating a vector with three 0
, then pushing back a further three elements. To instantiate a vector with values 1, 2 and 3, you can do this:
std::vector<int> myInts{1,2,3};
Alternatively, you can instantiate an empty vector, call reserve
to avoid re-allocations, and then push back the values:
std::vector<int> myInts;
myInts.reserve(3);
myInts.push_back(1);
myInts.push_back(2);
myInts.push_back(3);
The call to reserve
has the effect of allocating enough space for three elements, without initializing any elements.
Initializing variable length array
VLAs cannot be initialized by any form of initialization syntax. You have to assign the initial values to your array elements after the declaration in whichever way you prefer.
C11: 6.7.9 Initialization (p2 and p3):
No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
Initializing a Vector (C++)
You really should pick up your textbook, and start reading, preferably yesterday. Nevertheless, I'll address to each section separately.
Your code (changed slightly)
double average(int a, int b, int c, int d, int e, int f, int g)
{
vector<double>aa;
aa[0]=int a;
aa[1]=int b;
aa[2]=int c;
// etc.
}
Has a few problems. The error you received was due to all the lines that looked like aa[0]=int a;
The word int
is not supposed to be there. If you remove them, it should compile, and crash on runtime, as aa
still has a size of 0. You can either preallocate the vector (vector<double> aa(7);
) or use aa.push_back(aa);
.
In your second attempt
for(size_t j=0; j<=7; j++)
{
cout<<"Enter item # " <<(j+1);
cin>>a[j];
}
For starters, the first line should be for(size_t j=0; j<7; j++)
(missing the =
). a
should be the vector<double>
from the first attempt, and not the function argument.
Your lecturers code has the line
double average (const vector<int>& v)
The &
before the v
tells the function that it's not receiving a copy (by value) of the variable v
, but rather the original copy (by reference). Often, that means that if the function changes its value, then the calling functions copy is changed. Here, however, there is that magical word const
that disallows the function from changing the value(s).
Lastly, the static_cast<double>
is a form of casting (changing) the variable type from an int
to a double
. The reason for this is that 3/2 == 1
whereas 3.0/2 == 1.5
.
Double declaration and initialization of vector in a class, C++?
In your constructor:
Matrix::Matrix(int rows, int cols)
: m_nRows(rows),
m_nCols(cols)
{
std::vector <std::vector <double>> MATRIX(m_nRows, std::vector<double>(m_nCols, 0));
}
you define a brand new variable with the name MATRIX
, which is totally distinct from the member variable Matrix::MATRIX
.
To initialize the Matrix::MATRIX
member variable you should do it in the member initializer list, jut like for the m_nRows
and m_nCols
variables:
Matrix::Matrix(int rows, int cols)
: m_nRows(rows),
m_nCols(cols),
MATRIX(m_nRows, std::vector<double>(m_nCols, 0))
{
}
Vector initialization in thrust
void Vector_Initialize (thrust::host_vector<double> *A, double lb, double delta)
should be replaced with
void Vector_Initialize (thrust::host_vector<double> &A, double lb, double delta)
*A
means A is a pointer (may be to one vector or an array or vectors). &A
means A is a reference.
If you still want to stick with *A
(not recommended), replace
for (int i = 0; i < A.size(); i++)
A[i] = lb + i * delta;
with
for (int i = 0; i < A->size(); i++)
(*A)[i] = lb + i * delta;
and pass the address of h_V
to Vector_Initialize function.
Related Topics
How to Use Non-Default Delimiters When Reading a Text File with Std::Fstream
Profiler for Visual Studio 2008, C++
Differencebetween Using a Struct with Two Fields and a Pair
Clang Doesn't See Basic Headers
Initializing Std::String from Char* Without Copy
How Computer Does Floating Point Arithmetic
How to Call Derived Class Method from Base Class Pointer
Reason for Using Non-Type Template Parameter Instead of Regular Parameter
Consistent Pseudo-Random Numbers Across Platforms
Difference Between 'Strcpy' and 'Strcpy_S'
How to Build Google's Protobuf in Windows Using Mingw
Boost::Spirit Expression Parser
Boost.Python Not Supporting Parallelism
What Is a Curly-Brace Enclosed List If Not an Intializer_List