Is there a way to initialize first few elements of a vector after defining the size of the vector like -
vector<int> vec (10);
This doesn't work and produces a compiler error -
vector<int> vec(10) {1,2,3};
For example with arrays we can do the same thing like -
int arr[5] {1,2,3}; // This will initialize the first 3 elements of the array to 1,2,3 and the remaining two to 0.
In short, no. Your can fill out the entire list of things you want to be in the vector:
vector<int> vec{1, 2, 3, 0, 0, 0, 0, 0, 0, 0};
Which will give you a vector of 10 elements.
Or, you can create the vector, then call resize to make it larger (filling the remaining elements with 0):
vector<int> vec{1, 2, 3};
vec.resize(10);
You generally don't need to do this kind of thing to vector though, because unlike array, you can extend vector as needed, after creation:
vector<int> vec{1, 2, 3};
vec.push_back(4);
There isn't a way to do it all in one line like you can with an array. You can use
vector<int> vec{1,2,3};
vec.resize(10);
but that does make the code a little less easy to use. Another option is to wrap that in a function like
template <typename T>
auto make_sized_vector(std::intializer_list<T> il, std::size_t size = 0)
{
const auto vec_size = std::max(size, il.size());
vector<T> vec; // create vector
vec.reserve(vec_size); // allocate all the storage needed
vec.assign(il); // assign the elements
vec.resize(vec_size); // set the rest to zero
return vec;
}
and then you can use that like
auto vec = make_sized_vector<int>({1, 2, 3}, 10);
If you are concerned about passing the std::intializer_list by value see why is `std::initializer_list` often passed by value? for why that really isn't a concern.
In case you want to initialize a vector the way you describe, all at once, so that it can become (e.g.) a const member, this is always possible in C++, with just a bit of ugliness and twisting. Let’s say you have a class:
struct SomeClass {
SomeClass(const std::vector<int> &start, int rest, std::size_t size);
const std::vector<int> some_vector_; // This is const!
};
What the constructor could look like:
SomeClass::SomeClass(const std::vector<int> &start, int rest, std::size_t size)
: some_vector_{[&start, rest, size] {
std::vector<int> some_vector;
some_vector.reserve(size);
some_vector.insert(some_vector.end(), start.begin(), start.end());
some_vector.insert(some_vector.end(), size - start.size(), rest);
return some_vector;
}()} {}
Basically the problem boils down to: How do I do “something procedural” in an initializer list? To which the answer is: You invoke a function that returns the desired type.
To test the construct above:
#include <cstdint>
#include <iostream>
#include <vector>
namespace { /* SomeClass stuff from above goes here. */ }
int main() {
SomeClass sc{{1, 2, 3}, 0, 10};
for (int i : sc.some_vector_) std::cout << i << '\n';
}
There are (of course) plenty of ways to make it (slightly) more efficient if needed, such as
a templated variadic constructor to create the initial part of the vector,
a templated perfect-forwarding constructor to benefit from R-value containers, and
as a combined benefit of the above, arbitrary iterable containers as inputs and as the const member.
Related
I want to add the numbers of the array {1, 2, 3} to the array {7, 4, 6} so I can get an array {8, 6, 9} like this:
int main(){
int arr[] = {1, 2, 3};
int arr2[] = {7, 4, 6};
arr += arr2; // invalid operands of types ‘int [3]’ and ‘int*’ to binary ‘operator+’
}
std::valarray allows you to do this, with some minor changes to your code:
#include <iostream>
#include <valarray>
int main() {
std::valarray<int> arr{1, 2, 3};
std::valarray<int> arr2{7, 4, 6};
arr += arr2;
std::cout << arr[0] << arr[1] << arr[2];
}
Compared to the other C++ standard library containers, std::valarray is equipped with a fair number of "bulk" mathematical operations.
If the arrays are "fixed" at compile time using a constexpr function is also a good idea:
#include <array>
#include <iostream>
//
// Define an add function template
//
// This will provide compile time checking of equal array sizes
// so we have no need to check that condition at runtime (over and over again).
//
// By making it constexpr we can also use this function's results at compile time (See below).
// Also by using std::array you have a good example on how C++ can return
// arrays from functions.
//
// template makes the code reusable for multiple types and array sizes.
//
// typename type_t makes this function usable for all kinds of types so it isn't restricted to ints
// std::size_t N allows for the compiler to generate correct code for positive array sizes
//
// arr1, arr2 :
// Passed as const because the add function should never change the content of those arrays.
// type_t(&arr1)[N] is C++'s way of passing an array of known size
// so you don't have to pass pointers, pointers to pointers and a seperate size parameter
// Another option would be to use std::array<type_t,N>&, but this syntax for passing arrays
// is very useful knowledge.
//
// constexpr means, if you follow some rules you can use this function at compile time
// which means that the compiler will compile this function and then use it too
//
// auto return type means that you let the compiler work out what type you return
// this can help later when refactoring code.
//
template<typename type_t, std::size_t N>
constexpr auto add(const type_t(&arr1)[N], const type_t(&arr2)[N])
{
// You can't return "C" style arrays from functions but you can return objects.
// std::array is a wrapper object for arrays (with almost no overhead)
// the extra {} at the end will initialize all values in the array to default value for type_t (0 for ints)
// (one of the rules for constexpr, everything must be initialized)
std::array<type_t, N> retval{};
// a standard for loop
for (std::size_t n = 0; n < N; ++n) retval[n] = arr1[n] + arr2[n];
// return the array, since we return a std::array<type_t,N> that will also
// become the return type of the function (auto)
return retval;
}
int main()
{
// constexpr initialization allows these arrays to be used at compile time.
constexpr int arr[] = { 1, 2, 3 };
constexpr int arr2[] = { 7, 4, 6 };
// with constexpr ask the compiler to run add at compile time
// (if the rules for constepxr in add do not fully apply then
// the code will still be executed at runtime)
constexpr auto result = add(arr, arr2);
// static_assert, is like assert but then evaluated at compile time.
// if the assert fails then teh code will not compile.
static_assert(result[0] == 8);
static_assert(result[1] == 6);
static_assert(result[2] == 9);
// to show you can use the results at runtime too
bool comma{ false };
// this is a range based for loop
// using range based for loops ensures you never run out of the
// bounds of an array (reduces bugs)
//
// const auto &
// When looping over all the elements of the array
// value will be a const reference to the current element
// visited.
// a reference to avoid copying data (not so important for ints, but important for
// more complex datatypes)
// const because we are only using it, not modifying it.
for (const auto& value : result)
{
if (comma) std::cout << ", ";
std::cout << value;
comma = true;
}
return 0;
}
You're going to want another array to store your values, we'll call this arr3 and make it the same size as the other arrays.
int arr[] = { 1,2,3 };
int arr2[] = { 7,4,6 };
int arr3[3]{};
Then you're going to want to add values from arr and arr2 and put them in arr3
arr3[0] = arr[0] + arr2[0];
arr3[1] = arr[1] + arr2[1];
arr3[2] = arr[2] + arr2[2];
You could also do this easily with a loop.
for (int i = 0; i < 3; i++)
{
arr3[i] = arr[i] + arr2[i];
}
As you get more involved with vectors and matrices, you might want to consider using a proper algebra library like Armadillo. On Ubuntu you would just add
apt get install libarmadillo-dev
Then on your CMakeLists.txt
project(arma)
cmake_minimum_required( VERSION 3.0 )
find_package( Armadillo REQUIRED )
include_directories( ${ARMADILLO_INCLUDE_DIR} )
add_executable( testarma testarma.cpp )
And use it on your code
#include <armadillo>
#include <iostream>
int main()
{
using vec = arma::Mat<int>;
vec A{1, 2, 3};
vec B{4, 5, 6};
vec C = A + B;
std::cout << C << std::endl;
}
$ ./testarma
5 7 9
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?
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);
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)
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.
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.
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));
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.
What is the simplest way to convert array to vector?
void test(vector<int> _array)
{
...
}
int x[3]={1, 2, 3};
test(x); // Syntax error.
I want to convert x from int array to vector in simplest way.
Use the vector constructor that takes two iterators, note that pointers are valid iterators, and use the implicit conversion from arrays to pointers:
int x[3] = {1, 2, 3};
std::vector<int> v(x, x + sizeof x / sizeof x[0]);
test(v);
or
test(std::vector<int>(x, x + sizeof x / sizeof x[0]));
where sizeof x / sizeof x[0] is obviously 3 in this context; it's the generic way of getting the number of elements in an array. Note that x + sizeof x / sizeof x[0] points one element beyond the last element.
Personally, I quite like the C++2011 approach because it neither requires you to use sizeof() nor to remember adjusting the array bounds if you ever change the array bounds (and you can define the relevant function in C++2003 if you want, too):
#include <iterator>
#include <vector>
int x[] = { 1, 2, 3, 4, 5 };
std::vector<int> v(std::begin(x), std::end(x));
Obviously, with C++2011 you might want to use initializer lists anyway:
std::vector<int> v({ 1, 2, 3, 4, 5 });
Pointers can be used like any other iterators:
int x[3] = {1, 2, 3};
std::vector<int> v(x, x + 3);
test(v)
You're asking the wrong question here - instead of forcing everything into a vector ask how you can convert test to work with iterators instead of a specific container. You can provide an overload too in order to retain compatibility (and handle other containers at the same time for free):
void test(const std::vector<int>& in) {
// Iterate over vector and do whatever
}
becomes:
template <typename Iterator>
void test(Iterator begin, const Iterator end) {
// Iterate over range and do whatever
}
template <typename Container>
void test(const Container& in) {
test(std::begin(in), std::end(in));
}
Which lets you do:
int x[3]={1, 2, 3};
test(x); // Now correct
(Ideone demo)
One simple way can be the use of assign() function that is pre-defined in vector class.
e.g.
array[5]={1,2,3,4,5};
vector<int> v;
v.assign(array, array+5); // 5 is size of array.
One way can be to use the array's bound in one go like this:
int a[3] = {1, 2, 3};
vector<int> v(a, *(&a+1));
I want to add a value multiple times to an std::vector. E.g. add the interger value 1 five times to the vector:
std::vector<int> vec;
vec.add(1, 5);
vec should be of the form {1,1,1,1,1} afterwards. Is there a clean c++ way to do so?
It really depends what you want to do.
Make a vector of length 5, filled with ones:
std::vector<int> vec(5, 1);
Grow a vector by 5 and fill it with ones:
std::vector<int> vec;
// ...
vec.insert(vec.end(), 5, 1);
Or resize it (if you know the initial size):
std::vector<int> vec(0);
vec.resize(5, 1);
You can also fill with elements using one of the many versions of fill, for example:
fill_n(back_inserter(vec), 5, 1);
and so on.... Read the library documentation, some of these functions return useful information, too.
Just use std::vector::insert.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> a;
a.insert(a.end(), 5, 1);
for(auto const& e : a)
std::cout << e << std::endl;
return 0;
}
You can just use the std::vector constructor for this:
std::vector<int> vec (5,1);
The signature for this is:
vector (size_type n, const value_type& val)
The standard algorithm header has a number of functions which can be used in cases like this. std::fill_n would work for your case.:
std::fill_n (std::back_inserter(vec), 5, 1);
You can use the assign method:
vec.assign(5, 1);
This will delete any existing elements in the vector before adding the new ones.
Is there any problem with my code ?
std::vector<int[2]> weights;
int weight[2] = {1,2};
weights.push_back(weight);
It can't be compiled, please help to explain why:
no matching function for call to ‘std::vector<int [2], std::allocator<int [2]> >::push_back(int*&)’
The reason arrays cannot be used in STL containers is because it requires the type to be copy constructible and assignable (also move constructible in c++11). For example, you cannot do the following with arrays:
int a[10];
int b[10];
a = b; // Will not work!
Because arrays do not satisfy the requirements, they cannot be used. However, if you really need to use an array (which probably is not the case), you can add it as a member of a class like so:
struct A { int weight[2];};
std::vector<A> v;
However, it probably would be better if you used an std::vector or std::array.
You cant do that simply.
It's better you use either of these:
vector <vector<int>> (it's basically a two dimensional vector.It should work in your case)
vector< string > (string is an array of characters ,so you require a type cast later.It can be easily.).
you can declare an structure (say S) having array of int type within it i.e.
struct S{int a[num]} ,then declare vector of
vector< S>
So indirectly, you are pushing array into a vector.
Array can be added to container like this too.
int arr[] = {16,2,77,29};
std::vector<int> myvec (arr, arr + sizeof(arr) / sizeof(int) );
Hope this helps someone.
Arrays aren't copy constructable so you can't store them in containers (vector in this case). You can store a nested vector or in C++11 a std::array.
You should use std::array instead of simple array:
#include <vector>
#include <array>
std::vector<std::array<int, 2>> weights;
std::array<int, 2> weight = {1, 2};
weights.push_back(weight);
or with a constructor:
std::vector<std::array<int, 2>> weights;
weights.push_back(std::array<int, 2> ({1, 2});
One possible solution is:
std::vector<int*> weights;
int* weight = new int[2];
weight[0] =1; weight[1] =2;
weights.push_back(weight);
Just use
vector<int*> .That will definitely work.
A relevant discussion on the same topic : Pushing an array into a vector
Situation like:
int arr[3] = { 1, 2, 3 };
std::vector<int[]> v;
v.push_back(arr);
doesn't work with error "cannot initialize array in vector with .."
This, could be worked well
int * arr = new int[3] { 1, 2, 3 };
std::vector<int*> v;
v.push_back(arr);
To instantiate the vector, you need to supply a type, but int[2] is not a type, it's a declaration.