从另一个容器创建容器,在c ++中应用每个元素一些函数

Khu*_*hid 4 c++ containers iterator stl-algorithm c++11

我的问题很简单,参见示例:

std::array<int,6> a = {{0,1,2,3,4,5}}; // -- given container.
auto F = []( int i ) { return  i*i; }; // -- given function.

std::vector<int> v;  // need create

// my solution:
v.reserve( a.size () );
for( std::size_t i = 0; i < a.size(); ++i )
    v.push_back( F(a[i]) ); 



// but I need something like
   std::vector<int>v( a.begin(), a.end(), <|applying each element to F|> );
Run Code Online (Sandbox Code Playgroud)

我可以创建上面的容器,而不是显式调用reserve和任何重新分配吗?

编辑:

  1. 我想避免储备; 因为其他我的第一个解决方案对我有好处:)
  2. 我想避免任何调整大小; 因为默认情况下它会初始化每个元素.
  3. 我将在真实项目中使用它,其中可能包括许多第三方库(boost,Soft-STL,...).

Lig*_*ica 9

标准算法std::transform正是这样!

std::vector<int> v(a.size());
std::transform(
   std::begin(a), std::end(a),
   std::begin(v),
   F
);
Run Code Online (Sandbox Code Playgroud)

std::back_inserter如果您愿意,可以从空向量开始并使用:

std::vector<int> v;
std::transform(
   std::begin(a), std::end(a),
   std::back_inserter(v),
   F
);
Run Code Online (Sandbox Code Playgroud)

但是,如果你这样做,你将面临不必要的重新分配(除非你是reserve第一次,就像你原来的尝试一样).您可以自己决定您的优先级.


jua*_*nza 5

用途std::transform:

#include <algorithm> // std::transform
#include <iterator>  // std::back_inserter

....

transform(a.begin(), a.end(), back_inserter(v), F);
Run Code Online (Sandbox Code Playgroud)

您可能需要先拨打电话v.reserve(asize())以避免重新分配.

  • @KerrekSB我感觉特别懒.星期五是新的星期天. (2认同)
  • @KerrekSB什么是ADL?:P (2认同)

Max*_*kin 2

另一种解决方案是使用boost::transform_iterator. 好处是您可以将迭代器传递给容器构造函数。与使用std::back_inserter或必须调用reserveresize在目的地时相比,这避免了内存重新分配。全部都在一个声明中:

std::vector<int> result(
      boost::make_transform_iterator(std::begin(a), F)
    , boost::make_transform_iterator(std::end(a), F)
    );
Run Code Online (Sandbox Code Playgroud)

不过,您可以实现更简洁的语法,如下所示:

std::vector<int> result(transform_range(a, F));
Run Code Online (Sandbox Code Playgroud)

transform_range执行:

template<class Iterator>
struct AutoSequence
{
    Iterator const beg_, end_;

    template<class T>
    operator std::vector<T>() const {
        return {beg_, end_};
    }
};

template<class Function, class InSeq>
auto transform_range(InSeq const& in) -> AutoSequence<decltype(boost::make_transform_iterator<Function>(in.begin()))> {
    return {
          boost::make_transform_iterator<Function>(std::begin(in))
        , boost::make_transform_iterator<Function>(std::end(in))
        };
}

template<class Function, class InSeq>
auto transform_range(InSeq const& in, Function&& f) -> AutoSequence<decltype(boost::make_transform_iterator(in.begin(), f))> {
    return {
          boost::make_transform_iterator(std::begin(in), f)
        , boost::make_transform_iterator(std::end(in), f)
        };
}
Run Code Online (Sandbox Code Playgroud)

  • 完全没有必要使用第三方库。这给你带来了什么?这里保存一行代码,在标头中添加一千行代码。惊人的。 (2认同)
  • 那么,您衡量了性能优势吗?您还测量了编译时间的影响吗? (2认同)