It's oversimplified code with a simple vector and class.
class OutputClass
{
public:
OutputClass(int x, int y);
};
std::vector<OutputClass> Convert(std::vector<int> const &input)
{
std::vector<OutputClass> res;
res.reserve(input.size());
//either (1)
for (auto const &in : input)
res.emplace_back(in, in*in);
return res;
//or something like (2)
std::transform(input.begin(),
input.end(),
std::back_inserter(res),
[](InputClass const &in){return OutputClass(in, in*in);});
return res;
}
Is there a difference in performance between those two options? Static analyzers often have a rule for replacing all raw loops with algorithms, but in this case, it seems to me that looping with emplace_back would be more efficient, as we don't need either copy or move. Or I'm wrong and they are equal in terms of performance and (2) is preferable in terms of good style and readability?
To find out whether one is significantly faster than the other in a particular use case, you can measure.
I see no benefit in enforcing the creation of vectors. Avoiding that dynamic allocation when it isn't needed can be quite good for performance. Here is an example where vectors are used, but that's not necessary:
OutputClass
convert(int in)
{
return {in, in*in};
}
auto
convert_range(const auto& input)
{
return std::ranges::transform_view(input, convert);
}
#include <vector>
int main()
{
std::vector<int> input {1, 2, 3};
auto r = convert_range(input);
std::vector<OutputClass> output(r.begin(), r.end());
}
Related
I want to multiply and divide all the elements of std::vector by constant in the same way as it is performed in C++ for ordinary types: at least the result should be integer when input vector has integer type and floating-point type otherwise.
I have found the code for multiplication based on std::multiplies and modified it with the replacement std::divides. As the result, the code works but not in the order I want it:
#include <iostream>
#include <vector>
#include <algorithm>
// std::vector multiplication by constant
// http://codereview.stackexchange.com/questions/77546
template <class T, class Q>
std::vector <T> operator*(const Q c, const std::vector<T> &A) {
std::vector <T> R(A.size());
std::transform(A.begin(), A.end(), R.begin(),
std::bind1st(std::multiplies<T>(),c));
return R;
}
// My modification for division. There should be integer division
template <class T, class Q>
std::vector <T> operator/(const std::vector<T> &A, const Q c) {
std::vector <T> R(A.size());
std::transform(A.begin(), A.end(), R.begin(),
std::bind1st(std::divides<T>(),c));
return R;
}
int main() {
std::vector<size_t> vec;
vec.push_back(100);
int d = 50;
std::vector<size_t> vec2 = d*vec;
std::vector<size_t> vec3 = vec/d;
std::cout<<vec[0]<<" "<<vec2[0]<<" "<<vec3[0]<<std::endl;
// The result is:
// 100 5000 0
size_t check = vec[0]/50;
std::cout<<check<<std::endl;
// Here the result is 2
// But
std::vector<double> vec_d;
vec_d.push_back(100.0);
vec_d = vec_d/50;
std::cout<<vec_d[0]<<std::endl;
// And here the result is 0.5
return 0;
}
How can I write my operator correctly ? I thought that std::bind1st would call division by c for each element, but it does the opposite somehow.
EDIT: I understand that I can write a loop, but I want to do a lot of divisions for big numbers, so I wanted it to be faster...
Using std::transform with C++11, I'd suggest making a lambda (see this tutorial) instead of using bind:
std::transform(A.begin(), A.end(), R.begin(), [c](T val) {
return val / c;
});
In my opinion, lambdas are almost always more readable than binding, especially when (like in your case) you're not binding all of the function's parameters.
Although if you're worried about performance, a raw for loop might be slightly faster, as there's no overhead of the function call and creating the lambda object.
According to Dietmar Kühl:
std::transform() may do a bit of "magic" and actually perform better than a loop. For example, the implementation may choose to vectorize the loop when it notices that it is used on a contiguous sequence of integers. It is, however, rather unlikely to be slower than the loop.
auto c_inverse= 1/c;
std::transform(A.begin(), A.end(), R.begin(), [c_inverse](T val) {
return val * c_inverse;
});
Similar to the other post, but it should be mentioned that rather than division, you will most likely see performance gains by multiplying by the inverse.
Why make it only for vectors? Here's a way to make more generic, to work with many types of containers:
template <class container, class Q>
container operator/(const container& A, const Q c) {
container R;
std::transform(std::cbegin(A), std::cend(A), std::back_inserter(R),
[c](const auto& val) {return val / c; });
return R;
}
Sure, it is expected to be a bit slower than with pre-allocation for a vector, since the back_inserter will allocate dynamically as it grows, but well, sometimes it might be appropriate to trade speed for genericity.
There is already a question on how to concatenate two vectors: Concatenating two std::vectors. However, I found it appropriate to start a new one, as my question is a bit more specific....
I have two classes that look like this:
class AClass {
public:
std::vector<double> getCoeffs() {return coeffs;}
private:
std::vector<double> coeffs;
};
class BClass {
public:
std::vector<double> getCoeffs() {return ...;}
private:
std::vector<AClass> aVector;
};
What is the best way (i.e. avoiding unnecessary copying etc.) to concatenate the coefficients from each element in aVector?
My very first attempt was
std::vector<double> BClass::getCoeffs(){
std::vector<double> coeffs;
std::vector<double> fcoefs;
for (int i=0;i<aVector.size();i++){
fcoefs = aVector[i].getCoeffs();
for (int j=0;j<fcoefs.size();j++{
coeffs.push_back(fcoefs[j]);
}
}
return coeffs;
}
I already know how to avoid the inner for loop (thanks to the above mentioned post), but I am pretty sure, that with the help of some std algorithm this could be done in a single line.
I cannot use C++11 at the moment. Nevertheless, I would also be interested how to do it in C++11 (if there is any advantage over "no C++11").
EDIT: I will try to rephrase the question a bit, to make it more clear.
Concatenating two vectors can be done via insert. For my example I would use this:
std::vector<double> BClass::getCoeffs(){
std::vector<double> coeffs;
std::vector<double> fcoefs;
for (int i=0;i<aVector.size();i++){
fcoefs = aVector[i].getCoeffs();
coeffs.insert(coeffs.end(),fcoefs.begin(),fcoefs.end());
}
return coeffs;
}
Is it possible to avoid the for loop?
I could imagine that it is possible to write something like
for_each(aVector.begin(),aVector.end(),coeffs.insert(coeffs.end(),....);
You can do this in C++11:
std::for_each(aVector.begin(), aVector.end(), [&](AClass i){const auto& temp = i.getCoeffs(); coeffs.insert(coeffs.end(), temp.begin(), temp.end());});
C++03 is more difficult because it lacks lambdas and bind.
About as good as you can do is to use copy in your internal loop:
for(std::vector<AClass>::iterator it = aVector.begin(); it != aVector.end(); ++it){
const std::vector<double>& temp = it->getCoeffs();
coeffs.insert(coeffs.end(), temp.begin(), temp.end());
}
These are both essentially the same thing, though you could improve your runtime on both by returning a const std::vector<double>& from getCoeffs.
EDIT:
Arg, just saw you added insert to your question. I thought I was really going to help you out there. As a consolation tip, what you are really asking about here is flattening a std::vector of std::vectors. That has an answer here. But should you have access to boost you should look at: http://www.boost.org/doc/libs/1_57_0/libs/multi_array/doc/reference.html#synopsis
The first step is to avoid extra allocations. If you know that you won't be growing the return value, you can reserve to exactly the right size.
std::vector<double> BClass::getCoeffs(){
typedef std::vector<double> dvec;
dvec coeffs;
typedef std::vector<AClass> avec;
typedef std::vector<dvec> ddvec;
ddvec swap_space;
swap_space.reserve(aVector.size());
size_t capacity = 0;
for (avec::const_iterator it = aVector.begin(); it != aVector.end(); ++it) {
dvec v = it->getCoeffs(); // RVO elision!
capacity += v.size();
swap_space.push_back();
v.swap(swap_space.back());
}
dvec retval;
retval.reserve(capacity);
for (ddvec::iterator it = swap_space.begin(); it != swap_space.end(); ++it) {
retval.insert( retval.end(), it->begin(), it->end() );
}
return retval; // NRVO
}
this should avoid more than one allocation per AClass (as forced by their API! You should have a vector<?> const& accessor), plus one allocation for the return value.
Fixing AClass is advised.
I have a C++ application with a struct which looks like:
struct test_struc {
std::string name;
int x;
int y;
std::vector<int> data;
};
And I would like to transform two std::vector<test_struc> using the lines according to their data element in the structure. So far, I have the code:
std::vector<test_struc> first = <from somewhere else>;
std::vector<test_struc> second = <from somewhere else>;
std::vector<int> result;
std::transform (second.begin(), second.end(), first.begin(), result.begin(), op_xor);
where op_xor is:
int op_xor (int &i,
int &j) {
return i^j;
}
This works well if first and second are vectors of int, but since they are not, I don't know how to tell the code to use the data element of test_struc as arguments to std::transform.
Am I barking up the wrong tree? Or is there a way to do this?
Note that at least with a modern compiler, you probably want to implement the operation as a lambda expression, so it would look something like:
std::transform(second.begin(), second.end(),
first.begin(),
std::back_inserter(result),
[](test_struct const &a, test_struct const &b) {
return a.y ^ b.y;
});
Minor aside: as it was, you had UB, trying to write through result.begin() when the size of result was 0. You could either use back_inserter as above, or you could define result initializing its size to second.size().
Your binary functor must take two test_structs:
int op_xor (const test_struct& i,
const test_struct& j)
{
return 42; // replace wit your desired logic.
}
It isn't clear what exactly you want the functor to do, but it should operate on the test_structs and return an int.
Or use lambdas.
And remember size of other vectors must be the same or more than "second"
result.resize(second.size());
std::transform(second.begin(), second.end(), first.begin(), result.begin(),
[](test_struct & one, test_struct & two){ return one.x ^ two.x; });
But Jerry's example with back_inserter is better
Also you can do it using boost::transform and boost phoenix lambdas:
#include <boost/range/algorithm.hpp>
#include <boost/phoenix.hpp>
using boost::phoenix::arg_names::arg1;
using boost::phoenix::arg_names::arg2;
boost::transform(second, first, std::back_inserter(result), (&arg1)->*&test_struc::x ^ (&arg2)->*&test_struc::x);
First and second arguments of boost::transform are ranges, so you do not have to write second.begin(), second.end(), first.begin() here.
I have a function that takes a number and returns up to that many things (say, ints). What's the cleanest interface? Some thoughts:
Return a vector<int>. The vector would be copied several times, which is inefficient.
Return a vector<int>*. My getter now has to allocate the vector itself, as well as the elements. There are all the usual problems of who has to free the vector, the fact that you can't allocate once and use the same storage for many different calls to the getter, etc. This is why STL algorithms typically avoid allocating memory, instead wanting it passed in.
Return a unique_ptr<vector<int>>. It's now clear who deletes it, but we still have the other problems.
Take a vector<int> as a reference parameter. The getter can push_back() and the caller can decide whether to reserve() the space. However, what should the getter do if the passed-in vector is non-empty? Append? Overwrite by clearing it first? Assert that it's empty? It would be nice if the signature of the function allowed only a single interpretation.
Pass a begin and end iterator. Now we need to return the number of items actually written (which might be smaller than desired), and the caller needs to be careful not to access items that were never written to.
Have the getter take an iterator, and the caller can pass an insert_iterator.
Give up and just pass a char *. :)
In C++11, where move semantics is supported for standard containers, you should go with option 1.
It makes the signature of your function clear, communicating that you just want a vector of integers to be returned, and it will be efficient, because no copy will be issued: the move constructor of std::vector will be invoked (or, most likely, Named Return Value Optimization will be applied, resulting in no move and no copy):
std::vector<int> foo()
{
std::vector<int> v;
// Fill in v...
return v;
}
This way you won't have to deal with issues such as ownership, unnecessary dynamic allocations, and other stuff which are just polluting the simplicity of your problem: returning a bunch of integers.
In C++03, you may want to go with option 4 and take an lvalue reference to a non-const vector: standard containers in C++03 are not move-aware, and copying a vector may be expensive. Thus:
void foo(std::vector<int>& v)
{
// Fill in v...
}
However, even in that case, you should consider whether this penalty is really significant for your use cases. If it is not, you may well opt for a clearer function signature at the expense of some CPU cycles.
Also, C++03 compilers are capable of performing Named Return Value Optimization, so even though in theory a temporary should be copy-constructed from the value you return, in practice no copying is likely to happen.
You wrote it yourself:
... This is why STL algorithms typically avoid allocating memory, instead wanting it passed in
except that STL algorithms don't typically "want memory passed in", they operate on iterators instead. This is specifically to decouple the algorithm from the container, giving rise to:
option 8
decouple the value generation from both the use and storage of those values, by returning an input iterator.
The easiest way is using boost::function_input_iterator, but a sketch mechanism is below (mostly because I was typing faster than thinking).
Input iterator type
(uses C++11, but you can replace the std::function with a function pointer or just hard-code the generation logic):
#include <functional>
#include <iterator>
template <typename T>
class Generator: public std::iterator<std::input_iterator_tag, T> {
int count_;
std::function<T()> generate_;
public:
Generator() : count_(0) {}
Generator(int count, std::function<T()> func) : count_(count)
, generate_(func) {}
Generator(Generator const &other) : count_(other.count_)
, generate_(other.generate_) {}
// move, assignment etc. etc. omitted for brevity
T operator*() { return generate_(); }
Generator<T>& operator++() {
--count_;
return *this;
}
Generator<T> operator++(int) {
Generator<T> tmp(*this);
++*this;
return tmp;
}
bool operator==(Generator<T> const &other) const {
return count_ == other.count_;
}
bool operator!=(Generator<T> const &other) const {
return !(*this == other);
}
};
Example generator function
(again, it's trivial to replace the lambda with an out-of-line function for C++98, but this is less typing)
#include <random>
Generator<int> begin_random_integers(int n) {
static std::minstd_rand prng;
static std::uniform_int_distribution<int> pdf;
Generator<int> rv(n,
[]() { return pdf(prng); }
);
return rv;
}
Generator<int> end_random_integers() {
return Generator<int>();
}
Example use
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
using namespace std;
vector<int> out;
cout << "copy 5 random ints into a vector\n";
copy(begin_random_integers(5), end_random_integers(),
back_inserter(out));
copy(out.begin(), out.end(),
ostream_iterator<int>(cout, ", "));
cout << "\n" "print 2 random ints straight from generator\n";
copy(begin_random_integers(2), end_random_integers(),
ostream_iterator<int>(cout, ", "));
cout << "\n" "reuse vector storage for 3 new ints\n";
out.clear();
copy(begin_random_integers(3), end_random_integers(),
back_inserter(out));
copy(out.begin(), out.end(),
ostream_iterator<int>(cout, ", "));
}
return vector<int>, it will not be copied, it will be moved.
In C++11 the right answer is to return the std::vector<int> is to return it, ensuring that it will be either explicitly or implicitly moved. (Prefer implicit move, because explicit move can block some optimizations)
Amusingly, if you are concerned about reusing the buffer, the easiest way is to throw in an optional parameter that takes a std::vector<int> by value like this:
std::vector<int> get_stuff( int how_many, std::vector<int> retval = std::vector<int>() ) {
// blah blah
return retval;
}
and, if you have a preallocated buffer of the right size, just std::move it into the get_stuff function and it will be used. If you don't have a preallocated buffer of the right size, don't pass a std::vector in.
Live example: http://ideone.com/quqnMQ
I'm uncertain if this will block NRVO/RVO, but there isn't a fundamental reason why it should, and moving a std::vector is cheap enough that you probably won't care if it does block NRVO/RVO anyhow.
However, you might not actually want to return a std::vector<int> - possibly you just want to iterate over the elements in question.
In that case, there is an easy way and a hard way.
The easy way is to expose a for_each_element( Lambda ) method:
#include <iostream>
struct Foo {
int get_element(int i) const { return i*2+1; }
template<typename Lambda>
void for_each_element( int up_to, Lambda&& f ) {
for (int i = 0; i < up_to; ++i ) {
f( get_element(i) );
}
}
};
int main() {
Foo foo;
foo.for_each_element( 7, [&](int e){
std::cout << e << "\n";
});
}
and possibly use a std::function if you must hide the implementation of the for_each.
The hard way would be to return a generator or a pair of iterators that generate the elements in question.
Both of these avoid the pointless allocation of the buffer when you only want to deal with the elements one at a time, and if generating the values in question is expensive (it might require traversing memory
In C++98 I would take a vector& and clear() it.
I have several standard sets of integers that I need to be able to access from multiple translation units. The goal is to take these standard sets and put them into local sets depending on the context of the code.
For example, the best solution I have is:
#include <boost/assign/list_of.hpp>
#include <set>
const std::set<int> set9 =
boost::assign::list_of(4)(10)(108);
const std::set<int> set10 =
boost::assign::list_of(3)(5)(10)(108);
const std::set<int> set11 =
boost::assign::list_of(2)(3)(5)(101);
int main(void)
{
std::set<int> my_set(set9);
my_set.insert(set11.begin(), set11.end());
return 0;
}
They don't need to be constant globals, in fact, I would probably prefer functions, but if they are functions then I would have to add an extra line and extra set variable every time I want to use more than one.
It would look something like this (with one more standard set than before):
std::set<int> my_set(get_set9());
std::set<int> extra_line(get_set11());
my_set.insert(extra_line.begin(), extra_line.end());
std::set<int> another_extra_line(get_set12());
my_set.insert(another_extra_line.begin(), another_extra_line.end());
Unless I am missing something?
The reason I would prefer functions is that there is additional complexity. Among the constant sets there are repeated values with connected meanings so that I don't want to repeat them each time in case there is a change (and to prevent code duplication).
In my previous example say that 10 and 108 are connected and should always appear together. If these were functions I could just have get_set11() and get_set12() call a common function (like get_set2() which just has 10 and 108). However, with the constant set approach I'm not sure how to build these constant sets containing other sets. The best I've come up with is:
#include <boost/assign/list_of.hpp>
#include <set>
#define APPLY_COMMON_SET(prev) \
prev(10)(8)
const std::set<int> set2 =
APPLY_COMMON_SET(boost::assign::list_of);
const std::set<int> set9 =
APPLY_COMMON_SET(boost::assign::list_of(4));
const std::set<int> set10 =
APPLY_COMMON_SET(boost::assign::list_of(3)(5));
const std::set<int> set11 =
boost::assign::list_of(2)(3)(5)(101);
#undef APPLY_COMMON_SET
int main(void)
{
std::set<int> my_set(set9);
my_set.insert(set11.begin(), set11.end());
return 0;
}
Which works, but I'd prefer to avoid the pre-processor macro.
This doesn't compile, but I would like to be able to do something like this:
const std::set<int> set2 =
boost::assign::list_of(10)(108)
const std::set<int> set9 =
boost::assign::list_of(4) + set2;
const std::set<int> set10 =
boost::assign::list_of(3)(5) + set2;
Is there a way to do this without macros, or is that my only choice?
Any particular performance constraints? You could just implement the addition you use at the end:
typedef std::set<int> intset;
intset onion(intset lhscp, const intset &rhs) {
lhscp.insert(rhs.begin(), rhs.end());
return lhscp;
}
const intset set10 = onion(boost::assign::list_of(2)(5), set2);
A local macro (as you have here, the key is the #undef) is probably the cleanest solution as you present the problem. However, you've not said much about why you're doing this, and that information may provide a better solution.
I would use the macro in the "opposite" direction:
#define COMMON (10)(8)
const std::set<int> set10 =
boost::assign::list_of(3)(5) COMMON;
#undef COMMON
To steal and slightly tweak Steve's answer (since I can't edit it). I think the best solution is to implement operator+ for sets.
std::set<int> operator+(std::set<int> lhs, const std::set<int> &rhs)
{
lhs.insert(rhs.begin(), rhs.end());
return lhs;
}
After this is done it doesn't matter whether the sets come from global constants or functions, they can all go as arguments to the constructors:
#include <boost/assign/list_of.hpp>
#include <stdio.h>
#include <set>
typedef std::set<int> intset;
intset operator+(intset lhs, const intset &rhs)
{
lhs.insert(rhs.begin(), rhs.end());
return lhs;
}
const intset set2 =
boost::assign::list_of(10)(108);
const intset set9 =
boost::assign::list_of(4) + set2;
intset get_set11(bool flag)
{
if(flag)
return set2 + boost::assign::list_of(6);
else
return set9;
}
int main(void)
{
intset my_set(set9 + get_set11(true));
return 0;
}