std :: transform和move语义

时间:2011-06-06 03:12:04

标签: c++ stl c++11

我正在使用Boost.Filesystem来创建目录中的文件列表。我使用boost::filesystem::recursive_directory_iteratorstd::copy将每个路径作为boost::filesystem::directory_entry对象放入std :: vector中。我希望以std :: strings的形式输出到文件,所以我做了以下(\ n以避免使用<<):

std::vector<boost::filesystem::directory_entry> buffer; //filled with paths
...
std::vector<std::string> buffer_native(buffer.size());
//transform directory_entry into std::string, and add a \n, so output is formatted without use of <<
std::transform(buffer.begin(),buffer.end(),buffer_native.begin(), [](boost::filesystem::directory_entry de)->std::string
    {
        std::string temp=de.path().string();
        temp+="\n";
        return temp;
    }
    buffer.clear();
    std::copy(buffer_native.begin(),buffer_native.end(),std::ostream_iterator<std::string>(out_file));

然而,问题是它创建了两个向量,其原始值立即被清除,因为它不需要。这听起来像移动语义的完美位置,但是n3242只提供与C ++ 98相同的两个转换重载。是否可以使用std::transform实现移动语义?如果不是,那么编写自定义循环会更好吗?

我在Windows XP上使用GCC 4.5.2(MinGW)。

1 个答案:

答案 0 :(得分:9)

这似乎是make_move_iterator的作业:

std::transform(make_move_iterator(buffer.begin()),
                make_move_iterator(buffer.end()), buffer_native.begin(),
                [](boost::filesystem::directory_entry&& de) -> std::string
{
    // still makes copy :/ perhaps native() would work better, I don't know
    std::string temp = de.path().string();
    temp += "\n";

    return temp;
}

移动迭代器只是一个移动其取消引用结果的迭代器。请注意,类需要支持移动语义才能产生差异;我不知道Boost FS是否会这样做。


请注意,如果您的目标是在不同的行上输出它们,那么您做错了。格式化打印不应要求输入数据采用某种格式,这样会破坏目的。为数据添加新行只是为了将其格式化为新行是令人讨厌的。无论如何,它都由ostream_iterator处理:

std::copy(buffer.begin(), buffer.end(), //               vvvv
            std::ostream_iterator<std::string>(out_file, "\n"));

任何更复杂的东西,制作一个用于打印的lambda;不要事先修改数据。