How do I push vectors by reference? - c++

This code below doesn't work because I push_back the vectors a and b to the vector vector and then alter the vectors a and b. I want to alter the vectors a and b so that the vector vector suffers the same modifications. How do I do this?
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>>vector;
std::vector<int>a;
std::vector<int>b;
vector.push_back(a);
vector.push_back(b);
for (int i = 1; i <= 10; i++)
a.push_back(i);
for (int i = 11; i <= 20; i++)
b.push_back(i);
std::cout << vector[1][0];
std::cin.get();
}

You can use std::reference_wrapper (since C++11).
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.
e.g.
std::vector<std::reference_wrapper<std::vector<int>>> v;
std::vector<int> a;
std::vector<int> b;
v.push_back(a);
v.push_back(b);
for (int i = 1; i <= 10; i++)
a.push_back(i);
for (int i = 11; i <= 20; i++)
b.push_back(i);
std::cout << v[1].get()[0]; //11
LIVE
Note that if the vector has longer timelife than a and b, then when a and b get destroyed the references stored in the vector become dangled.

Create v (vector is not a good name since it shares with the library and makes the code confusing) to be a vector of vector pointers (since a vector of references is not possible):
std::vector<std::vector<int> *> v; //declare as vec of vec pointers
...
v.push_back(&a); //push_back addresses of a and b
v.push_back(&b);
...
std::cout << v.at(1)->at(0) //dereference and call at on the inner vec
Note that this can be dangerous if a or b go out of scope before v, as that will leave you with dangling pointers, a mess of undefined behavior and a murder time-consuming bugs.

The basic issue is that push_back copies its parameter to the end of the vector. To modify the object in the vector, you need to get a reference to it. One approach:
std::vector< std::vector<int> > my_vector;
my_vector.reserve(2); // Going over the allocation invalidates references
my_vector.push_back( std::vector<int>() );
std::vector<int> & a = my_vector.back();
my_vector.push_back( std::vector<int>() );
std::vector<int> & b = my_vector.back();
(I changed the name of the variable because using "vector" as a variable name tends to lead to confusion.)
If you can use C++17, there is a way to reduce the lines of code using emplace_back.

If you know the number of vectors ahead of time you can do it like this:
std::vector<std::vector<int>> v(2);
std::vector<int> &a = v[0];
std::vector<int> &b = v[1];
...

Related

Creating and storing objects in a container without using new?

Say I have the class
class A{
int value;
public:
A(int val) : value(val) {};
}
I store pointers of instances in a collection such as vector using for loop
std::vector<A*> myCollection;
for (int i = 0; i < 10; ++i){
myCollection.push_back(&A(i));
}
Now the for loop will construct and destruct an object at the same memory location resulting in a vector with 10 pointers pointing to the same address and dereferencing them will give A->value = 9.
Is there any way around this without dynamic allocation? And yes I have to use collection of pointers and not references.
If the objects need to be on the stack, but you also want a vector of pointers because of some API requirement, etc., Just create an array of the objects, then store the pointers. Be very mindful of the lifetime issues.
size_t const sz = 3;
A arr[sz] {1, 2, 3};
std::vector<A*> v;
v.reserve(sz);
for (auto& a : arr) v.push_back(&a);
someFunc(v);
The problem with your current program is that A(i) is a prvalue and hence its address using the & operator cannot be taken. This means that the following expression is invalid in your code:
//---------------------vvvvv----->invalid because A(i) is a prvalue
myCollection.push_back(&A(i));
You could instead use a std::vector<A> in addtion to std::vector<A*> as shown below:
std::vector<A> myVector;
myVector.reserve(10);
//-------^^^^^^^---------------->to avoid reallocations when capacity is not enough
for (int i = 0; i < 10; ++i){
myVector.emplace_back(i);
//-----------^^^^^^^^^^^^------->use emplace_back to forward the argument i
}
std::vector<A*> myPtrVector;
myPtrVector.reserve(10);
for(auto&elem: myVector)
{
myPtrVector.push_back(&elem);
}

Why is vector::clear not working inside foreach loop?

My code:
vector<int> v[10];
const int x = 3;
void clearBySimpleLoop(){
for (int i = 0; i < x; i++){
v[i].clear();
}
}
int main()
{
for (int i = 0; i < x; i++){
v[i].push_back(11+i);
v[i].push_back(11+i+1);
v[i].push_back(11+i+2);
}
for (auto vec : v) vec.clear(); //#01. Contents are not cleared. Size of the contained vectors remains same.
clearBySimpleLoop(); //#02. Contents are cleared. Size of the contained vectors becomes zero.
return 0;
}
Question is why does the code inside the foreach loop (#01) fails to clear the vector in the array, while a simple for loop (#02) does it successfully?
Demo: https://onlinegdb.com/B1m8-2jG4
When you write
for (auto vec : v) vec.clear(); //
then auto gets deduced as std::vector<int>, hence vec are copies of the elements of v. You clear the copies, but leave the actual elements unchanged. If you want to operate on the elements themself you have to use references:
for (auto& vec : v) vec.clear();
My personal rule of thumb is to always mention pointerness, constness and referenceness explicitly when using auto. I think it makes usages of auto much more readable, but thats just my opinion. Note that here you have no choice, but if you'd follow the rule you could have realized more easily that vec are values, not references.

Is there a way to move data from a vector to a dynamic array?

I use std::vector to do allocation for me in a function.When I'm done, I want to get plain data from it without extra copying. The data ptr will be handled by another class, so I can ditch the vector and I don't have to care if it's valid. Basically, I want to transfer ownership of vector's data. Is there a way to do this?
Transferring ownership is not possible by design of std::vector. However you may extend the lifetime of the vector by making it static and just using the pointer to the first element:
#include <iostream>
#include <vector>
int* getData()
{
static std::vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
return v.data(); // pointer to first element, equivalent to &v.front() or &v[0]
}
int main()
{
auto data = getData();
for ( std::size_t i(0); i < 4; ++i )
{
std::cout << data[i] << "\n";
}
}
Demo: http://ideone.com/hsrOeH
As the vector is static, the destructor isn't called at the end of scope (which is the end of the method getData()). Hence it is safe to use the pointer returned by .data() outside of this scope.

Strange error regarding STL vector of pointers

I've a small code snippet which produces an error on running. The following code stores data of mystruct and creates a vector of pointers which store the addresses of the corresponding data.
struct mystruct{
std::vector < int > someinfo;
int somenumbers;
double *somepointer;
double someparm;
void Print(){....}
};
void DoSomething(mystruct &_somestruct, std::vector< mystruct > &_somevec,
std::vector<mystruct *> &_ptr){
_somevec.push_back(_somestruct);
_ptr.push_back(&(_somevec.back()));
}
void ReadStruct(){
std::vector<mystruct > _vec;
std::vector<mystruct *> _ptr;
for(int i=0;i<100;i++){
mystruct _struct;
_struct.somenumbers = 3;
_struct.someinfo.push_back(0);
_struct.someinfo.push_back(1);
_struct.someinfo.push_back(2);
DoSomething(_struct, _vec, _ptr);
}
_vec[0].Print(); //Prints correctly
_ptr[0]->Print();//Prints garbage info
}
If I first create the vector and then create the vector of pointers then the code works perfectly i.e.
void DoSomething(mystruct &_somestruct, std::vector< mystruct > &_somevec){
_somevec.push_back(_somestruct);
//_ptr.push_back(&(_somevec.back()));
}
void DoSomething1(std::vector< mystruct > &_somevec, std::vector<mystruct *> &_ptr){
for(int i=0;i<_somevec.size();i++)
_ptr.push_back(&(_somevec[i]));
}
I do not know what mistake I am doing. Your help/inputs is greatly appreciated!!
This does not look very safe to me.
In _ptr.push_back(&(_somevec.back())); you are taking the address of an element in _somevec. But when _somevec is changed by e.g. a push_back the address will be invalid!
For example this will not work:
std::vector<int> v;
v.push_back(17);
int* p = &v.back(); // pointer is valid
for(int i=0; i<10; i++) v.push_back(0);
*p = 42; // ERROR: p is no longer valid!
You can make this a bit better by using reserve prior to using push_back.
std::vector<int> v;
v.reserve(100); // v will now have enough room to not reallocate memory
v.push_back(17);
int* p = &v.back(); // pointer is valid
for(int i=0; i<10; i++) v.push_back(0);
*p = 42; // (probably) OK: p is still valid
But I would not recommend to do this.
It looks as if you are inserting elements into one vector and reference them with pointers from another vector. However, there doesn't seem to be any precaution against the vector of objects running out of capacity and relocating the objects, invalidating all the pointer.
The easiest approach to verify this hypothesis is to see if the capacity() of the vector of objects ever changes. The easiest fix is probably to use a std::deque<mystruct> as a std::deque<T> doesn't relocate its objects when adding/removing objects at either end.

return underlying array from vector

Will the array be deallocated and if so, what is a workaround?
double * GetArrayFromVector( std::map<std::string, double> m, char ** names, int count )
{
if(!names) return 0;
std::vector<double> vec(m.size());
for (int i=0; i<count; ++i)
{
if(!names[i]) return 0;
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec.push_back(iter->second);
else
return 0;
}
return &vec[0];
}
Thanks a lot
Divide your function on two.
Make your functions make just one action:
1. fill vector from map.
2. create array from vector.
Don't forget to pass map by const reference.
Main note: caller of the GetArrayFromVector is responsible for memory deallocation.
void FillVector( const std::map<std::string, double>& m,
std::vector< double >& v,
char ** names,
int count )
{
.......
}
double* createArray( const std::vector< double >& v )
{
double* result = new double [v.size()];
memcpy( result, &v.front(), v.size() * sizeof( double ) );
return result;
}
// and finally your function
double* GetArrayFromVector( const std::map<std::string, double>& m,
char ** names,
int count )
{
std::vector< double > v;
FillVector( m, v, names, count );
return CreateArray( v );
}
Yes -- it's deallocated as soon as your return from the function, because vec is declared on the stack. The std::vector destructor takes care of freeing the memory. Since you're returning the address of a deallocated array, you're going to start messing around with deallocated memory, which is a big no-no. At best, you'll crash immediately. At worst, you'll silently succeed with a big gaping security hole.
There are two ways to fix this: (1) return the entire vector by-value, which makes a copy of the entire vector, or (2) return the vector via a reference parameter.
Solution 1:
std::vector<double> GetArrayFromVector(...)
{
...
return vec; // make copy of entire vec, probably not a good idea
}
Solution 2:
void GetArrayFromVector(..., std::vector<double> & vec)
{
// compute result, store it in vec
}
Yes the array will be deallocated.
Change the function to:
double * GetArrayFromVector( std::map<std::string, double> m, vector<double> &vec, char ** names, int count )
{
vec.clear();
vec.reserve(m.size());
for (int i=0; i<count; ++i)
{
if(!names[i]) return 0;
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec.push_back(iter->second);
else
return 0;
}
return &vec[0];
}
Or else use boost::shared_array (also, look at boost::scoped_array)
boost::shared_array<double> GetArrayFromVector( std::map<std::string, double> m, char ** names, int count )
{
boost::shared_array<double> vec(new double[m.size()]);
for (int i=0; i<count; ++i)
{
if(!names[i]) return boost::shared_array<double>();
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec[i] = iter->second;
else
return boost::shared_array<double>();
}
return vec;
}
vec is a local variable. Its scope is limited to the GetArrayFromVector() function only. Never return the address of a local variable. Either return the array by value:
std::vector<double> GetArrayFromVector( std::map<std::string, double> m,
char ** names, int count )
or, pass a reference to the vector as an output parameter:
void GetArrayFromVector( std::map<std::string, double> m,
char ** names, int count,
std::vector<double>& vec)
or, pass an output iterator:
void GetArrayFromVector( std::map<std::string, double> m,
char ** names, int count,
std::vector<double>::iterator vecIter)
The last two will require some careful implementation of the function definition and calling though.
Additionally, if you are game for a bit more adventure try this:
// you'd need to change the value to use when an element is not
// found in the map to something that suits your needs
double pred(std::map<char*, double> haystick, char* const needle) {
std::map<char*, double>::iterator i = haystick.find(needle);
return i != haystick.end() ? i->second : 0;
}
int main(int argc, char* argv[])
{
std::map<char *, double> m;
std::vector<char *> names;
std::vector<double> dv;
m[ "Sasha" ] = 729.0;
m[ "josh" ] = 8154.0;
names.push_back("Sasha");
names.push_back("JonSkeet");
names.push_back("josh");
// transform is part of STL's <algorithm> header
// it takes a container (actually a range -- [begin(), end())
// note it is a half-open range -----------^
// as is customary for all STL algorithms, applies the function
// or functor specified as the last parameter to each element of
// the sequence and writes the result back to another container
// specified via the output iterator -- the third argument
//
// since I have not reserved enough elements for the vector dv
// i cannot blindly use it -- i need a back_inserter to coax
// transform to push_back() instead of do an insert operation
// of course, for vectors, this is costly since reallocations
// may happen, but let's leave the performance aside for a while!
//
// ok, so what about the last parameter, you ask? it has to be an
// unary_operation. well, mostly so. but what is it that we want?
// we want to take an iterator from the original char* (string)
// array and see if there's an entry in the map. if there is one
// we retrieve the associated double value and put it in dv; else,
// we set a default value of 0 -- change it to whatever pleases you
// maybe a std::numeric_limit<double> if it works for you.
//
// you can create a functor inheriting std::unary_function and pass
// it on. that's the easy way out. but what if you already have a
// comparator, a C-style find() function? will it work? yes, it will.
// but we have to wrap it using the function adaptor std::ptr_fun
// to make the compiler happy (after all it wants a unary_function, right?)
//
// this simple scheme of things works very well, save for a last little
// glitch. the comparator actually takes two parameters -- a what to search
// and a where to search. and guess what -- the where to search is always
// fixed. so that gives us a good oppertunity to fix the first parameter to
// our map<char*, double> which is exactly what std::bind1st() does.
// surprisingly, now that you've fixed one function, you no longer have a
// binary function (one taking two arguments) but an unary one -- which is
// just what you'd pass to transform. voila!
std::transform(names.begin(), names.end(), std::back_inserter(dv),
std::bind1st(std::ptr_fun(pred), m));
std::copy(dv.begin(), dv.end(),
std::ostream_iterator<double>(std::cout, "\n"));
return 0;
}
Some interesting links:
transform [actually, comes in two flavors]
bind1st or binder1st [there's a binder2nd too!]
back_inserter
ptr_fun [check out mem_fun also]
unary_function [and there's binary_function]
Also check out Boost. They have done some magic with bind()!
You can pass it by reference or new/delete it, but as posted your vector will be destructed after the function returns.
Yes, the vector (and the data store it holds) will be deallocated when the function ends.
Why are you creating a vector? If you want an array, just create & fill one of those..
double * GetArrayFromVector( std::map<std::string, double> m, char * names[], int count )
{
if(!names) return 0;
double* vec = new double[m.size()];
int j = 0;
for (int i=0; i<count; ++i)
{
if(!names[i]) return 0;
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec[j++] =iter->second;
else
return 0;
}
return vec;
}
Yes the vector will be deallocated when the function exits (and the 'vec' variable goes out of scope). The pointer you return will therefore be invalid.
An alternative is to allocate the array on the heap (using the 'new' operator) and return that pointer instead, but it will be the caller's responsibility to 'delete' the pointer, which is usually frown upon.
A better alternative is to return a shared_ptr to your array.
Since you know count up front, there's no benefit to using an stl vector. You could simply do this:
double* GetArrayFromVector(std::map<char*, double> m, char** names, int count)
{
double* result = new double[count];
for (int i = 0; i < count; ++i)
{
if(!names[i])
{
delete[] result;
return 0;
}
map<std::string, double>::iterator iter = m.find(name[i]);
if(iter != m.end())
{
result[i] = iter->second;
}
else
{
delete[] result;
return 0;
}
}
return result;
}
Note that you are passing ownership of the allocated array to the caller. Personally, I'd try to write the code in a way that observes the RAII principle; either pass in a vector to be populated, or use a managed/shared pointer, etc. (both of these options have been suggested in other answers).
There is a concept call move constructors that would allow you to transfer the ownership of a resource held by a (stack-based) object to a new object. I have heard that STLport has a move_source template to accomplish this
This will be coming to C++0x.
In this case, you would be returning std::vector<double> instead of double*.
Kinda surprised no one has mentioned vector::swap. Have the caller pass in a reference to a vector which will have its contents replaced by the function:
void GetArrayFromVector( std::vector<double>& output, ... )
{
std::vector<double> vec(m.size());
// construct vec here...
output.swap(vec);
}
BTW: "GetArrayFromVector" and you pass in a map?
You could use std::auto_ptr smart pointer (but passing vector reference to your function is better solution).
Example of std::auto_ptr:
std::auto_ptr< std::vector<int> > getArray(int& count){
std::auto_ptr< std::vector<int> > vec(new std::vector<int>());
vec->push_back(10);
vec->push_back(12);
vec->push_back(14);
vec->push_back(16);
count = vec->size();
return vec;
}
int main(){
int size = 0;
std::auto_ptr< std::vector<int> > autoPtrVec = getArray(size);
int* ptr = &(*autoPtrVec)[0];
std::cout << "Size: " << size << std::endl;
for(int i=0; i<size; i++){
std::cout << "[" << i << "]=" << ptr[i] << std::endl;
}
return 0;
}
C++ vectors have a data() method which returns a pointer to the underlying array.
// vector::data
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (5);
int* p = myvector.data();
*p = 10;
++p;
*p = 20;
p[2] = 100;
std::cout << "myvector contains:";
for (unsigned i=0; i<myvector.size(); ++i)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
which outputs
myvector contains: 10 20 0 100 0