How to initialize a vector of distinct dynamically allocated addresses - c++

Is it possible to create a std::vector<T*> vec; during initialization, such that each element of vec stores a distinct address on the heap?
Simply doing
int N = 10;
std::vector<T*> vec(N, new T)
makes all elements of vec store the same address on the heap. Of course, I could simply just do
int N = 10;
std::vector<T*> vec(N);
std::for_each(vec.begin(), vec.end(), [](auto &ptr){
ptr = new int;
});
Is there any way to do it from within the constructor call?

Constructors that fill values into the vector all create duplicates of a single value, so they wont work in this case.
You can do a little better than std::for_each though. Since you want each element in the vector filled in with the result of a function, std::generate (or std::generate_n) is clearly a better fit:
std::vector<T *> vec(N);
std::generate(vec.begin(), vec.end(), [] { return new int; });
That said, a vector of raw pointers is most likely a mistake, so I'd recommend exploring other options.

Related

Applying stl algorithms to multidimensional vectors (vector<vector<T> >)

How, generally, can an stl algorithm be applied to a multidimensional vector (i.e. a vector<vector<T> >)?
For example, if I wanted to fill some vector, myVector, with values according to some function, myFunc(), I might use something like:
std::generate(myVector.begin() myVector.end(), myFunc())
Suppose now that myVec is a vector<vector<T> >. How might I use std::generate to populate every element of every vector in myVec according to myFunc? Need I use a loop (barring all other considerations)?
Would I simply write something like:
std::generate(myVec.begin(), myVec.end(), std::generate(...))
Surprisingly, I cannot find anything on this here or elsewhere.
The generator passed to std::generate() needs to return a type that is assignable to the element type of the container. So, in your example, the element type of myVector is another vector, so myFunc() would need to return a whole vector, eg:
template<typename T>
vector<T> myFunc()
{
vector<T> v;
// populate v as needed...
return v;
}
vector<vector<T> > myVector(some size);
std::generate(myVector.begin() myVector.end(), myFunc<T>);
Otherwise, you will have to do something more like this instead:
template<typename T>
void myFunc(vector<T> &v)
{
// populate v as needed...
}
vector<vector<T>> myVector(some size);
for(auto &v : myVector) {
myFunc(v);
}
With range library (as range-v3), you might flatten your vectors to work with vector of less dimension:
std::vector<std::vector<int>> v(4, std::vector<int>(3));
auto flattened = v | ranges::view::join;
std::generate(begin(flattened), end(flattened), [n = 0]() mutable{ return n++; });
Demo
Else, regular loop seems the simpler:
auto gen = [n = 0]() mutable{ return n++; }
for (auto& inner : v) {
std::generate(begin(inner), end(inner), gen);
}
You cannot really nest generate calls as it doesn't take current element to know size of each inner vector.

Is there a noop iterator in the stl?

If I wanted to copy the same value across an iterator range, I would think that it would be easy to have a noop iterator where you pass it a value, and when it is incremented, it would not move anywhere. This would allow using the existing std::copy and std::copy_if algorithms.
However, I can't seem to find such a beast. Am I going to have to roll my own?
Use std::fill or std::fill_n algorithm.
Some containers, e.g. std::vector<> and std::list<>, have a constructor with size and initializer:
std::vector<int> v(10, 42); // 42 is the initializer
v.resize(20, 42); // Initialize new elements with 42.
As far as I know there is no iterator for this but there is an algorithm. std::generate will take a range an assign a value to each element that is returned from the generator passed to it. If you want to assign everything 42 for instance that would look like
std::vector<int> vec(20);
std::generate(vec.begin(), vec.end(), []() { return 42; });
You can even get values that change like
std::vector<int> vec(20);
std::generate(vec.begin(), vec.end(), []() { static int counter = 0; ++counter; return counter * counter; });

Faster to swap or assign a vector of strings?

I have a class with a vector of strings and a function that assigns to that vector. I am changing my function to only assign to the vector if it's successful. To do that I use a temporary vector of strings in the function and then if the function is successful I assign to the vector of strings in the class.
For example:
class test
{
vector<string> v;
void Function()
{
vector<string> temp;
v = temp; // Is this better?
v.swap( temp ); // Or instead is this better?
}
};
In C++11, move it:
v = std::move(temp);
In ancient dialects, swapping would be better than copy-assigning (assuming the vector isn't empty as it is in your example).
Moving or swapping just needs to modify a few pointers, while copying requires memory allocation and other expensive shenanigans.
From the complexity point of view std::swap algorithm should be preferred.
vector<string> temp;
v = temp; // complexity is linear in the size of the temp
v.swap( temp ); // complexity is constant

Best way to delete a std::unique_ptr from a vector with a raw pointer?

So I have a vector like so:
std::vector<std::unique_ptr<SomeClass>> myVector;
Then I have another vector which contains raw pointers of SomeClass:
std::vector<SomeClass*> myOtherVector;
If there is an element inside myOtherVector it will also be inside myVector, so I want to go through each element in myOtherVector and remove the same element from myVector. Then clear out the vector. This is what I came up with:
for(size_t i = 0; i < myOtherVector.size(); i++)
{
myVector.erase(std::remove(myVector.begin(), myVector.end(), myOtherVector[i]), myVector.end());
}
myOtherVector.clear();
This produces a compile time error because myVector holds unique pointers but I'm giving the remove() function a raw pointer. This is where I need help because I don't know what the proper way to solve this problem would be. I changed the line to:
myVector.erase(std::remove(myVector.begin(), myVector.end(), std::unique_ptr<SomeClass>(myOtherVector[i])), myVector.end());
Frist of all this is incorrect because now I have two std::unique_ptrs referencing the same object. The element inside myVector contains a reference and the construction of the unique pointer in the above line is another reference. And I don't even know if constructing a new pointer to get the same type is conceptually the correct way to go about doing this. So then I changed the unique pointers to shared pointers:
std::vector<std::shared_ptr<SomeClass>> myVector;
std::vector<SomeClass*> myOtherVector;
for(size_t i = 0; i < myOtherVector.size(); i++)
{
myVector.erase(std::remove(myVector.begin(), myVector.end(), std::shared_ptr<SomeClass>(myOtherVector[i])), myVector.end());
}
myOtherVector.clear();
When I ran the application the myVector.erase() line resulted in a runtime error which said "ApplicationName.exe has triggered a breakpoint." upon clicking continue I got a debug assertion failure.
So obviously I'm doing something wrong, but I don't know what. What is the correct way to erase a smart pointer from a vector with a raw pointer?
This is how I would do it. Performance could be improved, but as long as it won't prove to be a bottleneck for your application, I would not bother with that. The algorithm is simple and clear.
It uses remove_if to selectively remove from the first container (myVector) all the elements pointing to objects that are pointed to by elements of the second container (myOtherVector); then, it clears the second container. The predicate is implemented through a lambda function:
#include <vector>
#include <memory>
#include <algorithm>
struct SomeClass { /* ... */ };
int main()
{
std::vector<std::unique_ptr<SomeClass>> myVector;
std::vector<SomeClass*> myOtherVector;
myVector.erase(
std::remove_if( // Selectively remove elements in the second vector...
myVector.begin(),
myVector.end(),
[&] (std::unique_ptr<SomeClass> const& p)
{ // This predicate checks whether the element is contained
// in the second vector of pointers to be removed...
return std::find(
myOtherVector.cbegin(),
myOtherVector.cend(),
p.get()
) != myOtherVector.end();
}),
myVector.end()
);
myOtherVector.clear();
}
std::unique_ptr has a member function, get, that returns the owned pointer.
Consider the following:
std::sort(myOtherVector.begin(), myOtherVector.end());
myVector.erase(std::remove_if(myVector.begin(), myVector.end(),
[&](std::unique_ptr<SomeClass> const& p) -> bool
{
return std::binary_search(myOtherVector.begin(), myOtherVector.end(),
p.get());
}));
myOtherVector.clear();
If you cant simplify your problem, how about std::set_difference or one of its kin (http://www.cplusplus.com/reference/algorithm/set_difference/)?
You would need to specify a compare function to get() the raw pointer from the unique_ptr

Initialize vector of structures

Let's I have
struct Vector {
float i,j,k;
}
I want to zero all elements of vec declared below (i,j,k=0)
std::vector <Vector> vec;
vec.resize(num,0);
I don't want to use reserve() and then push_back() zeroes one by one.
Another thing is, after succesfully initializing vec, I want to set all members of vec to zero again after it is manipulated. Is there something like memset for vectors?
EDIT:
I compared all of the methods in Mike Seymour's and Xeo's answers and as a result
size_t size = vec.size();
vec.clear();
vec.resize(size); is the fastest if they are repeated frequently in a loop.
That's very simple:
vec.resize(num);
or initialise it with the required size:
std::vector<Vector> vec(num);
Both the constructor and resize will fill new elements with value-initialised objects. A value-initialised object of a type with no default constructor (such as your Vector) will have all numeric members initialised to zero.
To reset everything to zero, either
size_t size = vec.size();
vec.clear();
vec.resize(size);
or:
std::fill(vec.begin(), vec.end(), Vector());
or, less efficiently but with a strong exception guarantee:
std::vector<Vector>(vec.size()).swap(vec);
C++ way of setting all current elements to 0:
std::fill( vec.begin(), vec.end(), 0 );
Or, alternatively, to re-initialize to a given size:
vec.clear();
vec.resize(num, 0);
This might not be as performant as memset, but good enough for 99% of the cases.
You can just use memset, so long your Vector is a POD type:
std::vector<Vector> v(num, 0); // inital fill
// do stuff
memset(&v[0], 0, sizeof(Vector) * v.size());
Though the C++ version would be with std::fill
#include <algorithm>
std::fill(v.begin(), v.end(), 0);