To create an array of strings this works:
std::string array[] = {
"first",
"second",
:
"last"
};
If I try to do the same with vectors it doesn't work:
std::vector<int> array[] = {
{1, 2},
{3, 4, 5}
:
{9}
};
I get "non-aggregates cannot be initialized with initializer list".
What is the correct syntax to initialise the array of vectors?
Note that I need to do it in one go like this and not using vector member functions to fill the vectors with ints one at a time (because I'm trying to set up a file that will create the array at compile time based upon the initialisation numbers, so calling member functions doesn't help in this case).
Although the purpose of using an array of vectors is very much questionable (why not use vector of vectors or a two-dimentional array then?), to do what you want the correct syntax would look like:
std::vector<int> array[] = {
vector<int>(2),
vector<int>(3),
//...
vector<int>(1)
};
The reason it doesn't make any sense, is because in this case it's semantically the same as creating an array of pointers:
int* array[] = {
new int[0],
new int[0],
//...
new int[0],
};
with the only difference is that internally std::vector is managing the lifetime of these pointers all by itself. That means that unless you're creating a constant-size vector (i.e. without a possibility for the vector to have its internal memory re-allocated, which is possible, if you're either declaring the vector to be const or simply make sure you don't ever call resize, reserve, push_back, insert, erase and other similar methods on it), you're going to get effectively an array of small objects with a pointer inside. This is how vector is usually implemented.
It's not clear, what you mean by creating an array on compile time. Arrays declared in the manner you try to do, as well as these:
int fixed_size_array[100];
are indeed created in such a way, than their size is determined on compile time. But vectors are a different beast -- these are complex C++ objects, which manage their memory dynamically in run-time, which means that they simply cannot have a compile-time fixed size by design.
To make a long story short, it's simply not supported. There are various workarounds to get similar syntax (e.g. Boost::assign) but these don't change what you get in the executable -- they just make calling the member functions a bit simpler than a string of calls to push_back.
Maybe something like this will take you in the direction you want?
const int arr[] = { 1, 2, 3, 4, 5 };
std::vector v( arr, arr + sizeof(arr) / sizeof(*arr) );
to create a vector of vector code
std::vector< std::vector< int > > v;
calling the default no argument constructor
create a Simple vector of int
int arry[] = {1,2,3,4,5};
std::vector< int > list(arry, arry + sizeof(arry) / sizeof(int));
Thus constructed a vector from an Integer array
I'd recommend you to use push_back() Method Instead in your Scenario.
However If you just wanna get dirty you can follow the way mentioned above and create an array of std::vector< int > and pass it to the constructor of std::vector< std::vector< int > >
Check http://www.cplusplus.com/reference/stl/vector/vector/ for more Information
You might be interested on this specific Constructor overload template <class InputIterator> vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
Neel
Related
I know in c++11 I can use initializer to create array/vector elements one by one like:
int ar[10]={1,2,3,4,5,6};
vector<int> vi = {1,2,3,4};
This is done manually, but what if I wish to initialize an array/vector with 10000 elements and specify their value, can it be done in one statement, RAII pattern?
E.g. I've defined a class:
class Somebody{
int age;
string name;
public:
Somebody():age(20),name("dummy"){} // default ctor
Somebody(int a, const char* n):age(a),name(n){} // but I wish to call this ctor
Somebody& operator = (const Somebody& s) {...}
};
Then in main function:
int main(int argc, char const *argv[])
{
Somebody obj(2, "John"); // parameterized ctor
Somebody ar[300]; // initialized, but called default ctor
for(int i=0;i<300;++i){ // initialize again in a loop
ar[i] = ... ; // call operator =
...
Question: could Somebody ar[300] be constructed with parameterized ctor?
If not, then I have to create this object array ar first(Compiler generated code will loop and call default parameter), then apply value changes for each object. This seems quite a bit redundant of cpu cycles.
Is there a way to do what I expected with just one call? (Loop and update each array element with parameterized ctor)
Thanks.
You can not do this with C-style arrays. One of the many reasons you should not be using them in the first place.
You should be using std::vector, which provides a constructor to populate the vector using a single value:
std::vector<Somebody> ar{300, Somebody("42", "filler")};
But often it is better to not create such dummy entries in the first place. A std::vector can grow dynamically so you can just add Somebody objects to it as you get their age and name.
std::vector people;
people.reserve(2); // optional but makes adding lots of objects more efficient
Somebody adam(42, "Adam");
people.push_back(adam);
people.emplace_back(23, "Eve");
This shows you 2 ways to add objects to the vector, the push_back adds objects to the vector (copies/moves it) while emplace_back will construct the object directly in the vector, which is often more efficient.
If you want a fixed size array then you can use
std::array<Somebody, 300> ar;
ar.fill(Somebody(23, "filler"));
But this has the same problem as the C-style array of using the default construtor. std::arrays::fill replaces all the objects with a new value.
Unfortunately there is no array constructor to do this in one go which is rather unfortunate.
Well, with simple arrays there's always the direct approach:
Somebody ar[300]={ {1, "Larry"}, {2, "Moe"}, {3, "Curly"} ... };
You'd have to write out whatever you want to write out 297 more times. This gets real old, real quickly.
One could potentially concoct, in a pinch, something that involves a variadic template to generate the whole bunch of them. Something like that is the classical approach to generating a fast 256-value array lookup for a textbook-style base64 decoder.
But for the simplistic case where you only want the same value, just #n copies of it, the simplest solution is to use a std::vector instead of a plain array and use one of its contructors that takes a single object and the vector size, and then constructs the vector by copying the object the requisite number of times. That involves slightly more overhead but is generally good enough, for this simple use case.
You can use std::fill_n:
Somebody obj(2, "John");
Somebody ar[300];
fill_n(ar, 300, obj);
I have a vector of 3 values in two different forms, and I would like to pass from one to the other:
a std::vector< float[3] >, std::vector< std::vector<float> > or even float[][3] if needed (that's the part I can change)
a std::vector of the color class
Let's work with these classes:
class color{
float x,y,z;
//some methods but no other member
}
What I would like to do:
std::vector<float[3]> myVector; // already allocated and filled
std::vector<color> cv = std::move( myVector ); // of course does not compile
My issue is that I didn't figure out how to convert one to the other without having to reallocate memory.
I can convert a float[3] into color using static_cast but it seems it does not work for a vector.
I would like not to iterate over the whole array and simply move the data from myVector inside the cv vector. I thought converting the pointer of myVector to void* and then to color3* could work, but I didn't succeed.
Ideas?
You cannot have a std::vector<float[3]> at all prior to C++20 because float[3] didn't meet the requirements of the value type that std::vector had. Since C++20 it technically is allowed, but is still not useful in practice since any member function that adds elements does still have requirements not satisfied by arrays.
Let's assume that you were asking a similar question where you have two different classes, where one is color and the other contains an array as a member. Such as std::array<float, 3>.
I would like not to iterate over the whole array and simply move the data from myVector inside the cv vector.
There is simply no way to avoid that. The only way to "move" data into a vector without iteration is to move from another vector of the same type. That singular case doesn't apply to your case of different types, so you must have iteration. You don't necessarily need to write the loop yourself, as you may use a standard algorithm instead. Here is an example using standard ranges:
std::vector<std::array<float,3>> myVector; // already allocated and filled
std::vector<color> cv;
auto arr_to_color = [](const std::array<float,3>& arr){
// assuming such constructor exists
return color(
arr[0],
arr[1],
arr[2]);
};
std::ranges::transform(
myVector,
std::back_inserter(cv),
arr_to_color);
I was reading about the key differences between std::array and C type array and came to know that one of the key differences is that C type array when called to an API go as a pointer while a copy of std::array gets passed. One of the blogs mentioned that as an advantage but I don't think so. What are the key advantages of using an std::array over C-type array? My exploration and understanding suggests that almost everything can be done with C type arrays. They can even be passed to STL algorithms. So I don't see any key advantage of using std::array over C-type array. Is that actually so?
It's true that everything you can do with std::array could be done with C array. Actually, std::array simply wraps a fixed size C array internally. However, std::array is often more convenient.
Ability to pass an array by value is an advantage. If you'd like to do this with C array, you'd have to pass a pointer and size and then create local copy. With std::array, you can avoid this, and choose what better suits your needs:
void takeArrayByValue(std::array<int, 5> arr)
{
arr[0] = newValue; // arr is a local copy, caller does not see this
}
void takeArrayByReference(std::array<int, 5>& arr)
{
arr[0] = newValue; // variable passed as argument is modified
}
// compare with this:
void takeCArrayAndMakeLocalCopy(const int (&arr)[5])
{
int localArr[5];
std::copy(std::begin(arr), std::end(arr), localArr);
// do something with localArr
}
Another thing: it's easier to misuse C arrays:
void takeCAray(int arr[5]);
int arr[3];
takeCArray(arr); // compiles
In this example, takeCArray really takes a pointer. It should have been takeCArray(int (&arr)[5]), but compiler won't complain about this, and the bug can potentially stay unnoticed at first. This can't happen with std::array:
void takeStdArray(std::array<int, 5>& arr);
std::array<int, 3> arr;
takeStdArray(arr); // compiler error!
I want to write a function to create an array with a viewed vector.
Such as
int foo(vector<int> &A){
int N=A.size();
int myarray[N]={0}; //here is an error
}
Here are my questions:
I know to build an array must use const value but vector::size() isn't return a const value?
using const modify the expression doesn't work N still a variable.
I don't see why you ever should need to create an array. If you pass arrays anywhere into a function, you pass a pointer to such an array. But you easily can get the vector's internal data as such a pointer:
std::vector<int> v({1, 2, 3, 4});
int* values = v.data();
Done, you have your "array", and you don't even have to copy the data...
If you still need a copy, just copy the vector itself.
Side-note: The vector's content is guaranteed by the standard to be contiguous, so you won't get into any trouble iterating over your "arrays".
However, one problem actually exists: If you want to store pointers to the contents of your array, they might get invalidated if you add further elements into your vector, as it might re-allocate its contents. Be aware of that! (Actually, the same just as if you need to create a new array for any reason...)
I want to know if there is a way to keep track of addresses of elements in a vector.
I like to use vector of solid elements like std::vector<MyObject> vec because:
std::vector do all the allocation / deallocation stuff for me
it also ensures me that my elements are stored in contiguous memory
I can get benefits of all code that work with vectors (e.g. <algorithm>)
This is exactly what I want. The problem arises when I want to store the address / reference of elements of my vector in other objects. In fact, the problem really arises when std::vector need to reallocate memory.
I tried to find alternatives to my problem:
Use vector of pointers / smart pointers : No, the pointers will be allocated contiguously but not the elements
Use vector of pointers / smart pointers and write my own operator new/new[] for MyObject : Humm, that seems better but no. By using a vector to allocate my elements I can say : "those particular set (I do not refer here to std::set) of elements must be allocated contiguously, not all". In fact I may want to have other set of elements that should be allocated contiguously because of the way I want to use them and using a vector to do that is exactly what (I think) I need. Thats also implies that I'm doing the job I want the vector to do.
Why not using boost multi-index? : In some ways that will do what I want because I want to store pointers/smartpointers of my vector elements in other containers. But no again because I really want to store reference/pointer/smartpointer of my vector's elements inside other objects, not just other containers.
What I would loved to have is a vector that can give me a pointer object that will allways point the the address of the desired element and I will use it like that :
std::vector<MyObject> vec;
// insert some elements
...
// get a pointer object by index or by using an iterator
// does something like that exist?
std::vector<MyObject>::pointer ptr = vec.get_pointer_at(5);
// do what I want on the vector except removing the element
...
// use my pointer whatever reallocations occurred or not
ptr->doSomething();
That sounds like an iterator that will never be invalidated except the fact I don't need/want to perform arithmetic on it (+x, -x, ++, --).
So, can someone leads me to the way to achieve what I want or explain me why/where I'm wrong wanting to do this? Please accept my apologize for my lack of knowledge in STL if there is a well known solution that I missed / or if this question has already be answered.
Edit:
I think that if I have to code such kind of pointer, that means that I'm wanting something useless or I'm wrong somewhere (unless someone should have already wrote a template for that) . So I'm more looking to a validated C++ idiom to get rid of this problem.
Although std::vector does not give you such pointer, there is no reason why you cannot make one yourself. All it takes is a class that keeps a reference to the std::vector object and the index, and overloads the prefix operator * and the infix operator -> (you need four overloads - const and non-const for each operator).
You would use this pointer like this:
std::vector<int> vect = {2, 4, 6, 8, 10, 12, 14, 16};
vect_ptr<int> ptr(vect, 5); // <<== You need to implement this
*ptr = 123;
cout << *ptr << endl;
The implementation of these overloads would grab the std::vector's begin() iterator, and return the result of calling vect.at(index). This would look like a pointer from the outside, but the object to which it points would change as the content of the std::vector gets resized.
As far as I know, there is nothing in the standard library nor in Boost to address your problem. A solution would be to implement your own kind of element pointer:
template<typename T>
class vector_element
{
public:
vector_element( std::vector<T>& v, std::size_t i )
: m_container( v ), m_element_index(i)
{ }
T& operator*() { return m_container[m_element_index]; }
T* operator->() { return &m_container[m_element_index]; }
private:
std::vector<T>& m_container;
std::size_t m_element_index;
};