如何不带push_back的容器使用std :: transform?

时间:2019-06-04 13:14:50

标签: c++ iterator

我有一个没有push_back()方法的容器。但是此容器在begin()end()上有一个迭代器。

我想使用std::transform()输出到该容器中。但是std::back_inserter需要在输出容器上调用push_back()

是否可以使用std::transform()输出到仅支持直接分配的容器中?喜欢:

for (auto item : containerNoPushBack)
{
    item = calculateValue();
}

或像这样的索引分配:

for (size_t i = 0; i < containerNoPushBack.size(); ++i)
{
    item[i] = calculateValue();
}

3 个答案:

答案 0 :(得分:3)

如果您可以执行item[i](即您的容器中有足够的元素),则只需在your_container.begin()中使用std::transform,而无需使用std::back_inserterstd::back_inserter只是避免在应用容器之前显式调整容器大小的好方法。

以下片段均将my_output的内容填充到my_input中:

std::vector<int> my_output;
std::transform(my_input.begin(), my_input.end(), std::back_inserter(my_output), [](const auto& arg){return arg;});

std::vector<int> my_output;
my_output.resize(my_input.size());
std::transform(my_input.begin(), my_input.end(), my_output.begin(), [](const auto& arg){return arg;});

答案 1 :(得分:2)

std::transform确实使用“直接分配”。仅当您需要推送元素时才使用back_inserter,如果目标中已有元素,则不需要。

考虑可能的实现方式(取自cppreference):

template<class InputIt, class OutputIt, class UnaryOperation>
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, 
                   UnaryOperation unary_op)
{
    while (first1 != last1) {
        *d_first++ = unary_op(*first1++);
    }
    return d_first;
}

std::transform本身不执行任何操作。正是由于这个原因,您需要一个back_inserter。但是,您可以调整目标的大小以为转换后的元素留出足够的空间。

答案 2 :(得分:1)

只需将普通的std::transformbeginend迭代器一起使用。不需要std::back_inserter甚至不需要std::inserter

例如,std::array不支持push_back方法,但是std::transform可以使用它:

#include <iostream>
#include <array>
#include <algorithm>
#include <vector>

int main() {
    std::vector<int> data = {1, 2, 3, 4, 5};

    std::array<int, 5> arr{};

    // note the lack of std::back_inserter just below
    std::transform(data.cbegin(), data.cend(), arr.begin(),
            [](auto i) {
                return i * i;
            });

    for (const auto i : arr) {
        std::cout << i << ' '; // prints 1, 4, 9, 16, 25
    }
}