可以就地工作的功能

时间:2017-09-24 21:35:19

标签: c++

我有以下功能:

shared_ptr_of_points filter(const shared_ptr_of_points input){
    shared_ptr_of_points result = make_new();
    for(const auto item:input->points){
         if(cond(item)){
            result->add_point(item);
         }
    }
    return result;
}

典型用途是:

auto filtered_points = filter(some_noisy_points);

但是,它可能以另一种方式使用:

some_points = filter(some_points);

在这种情况下,上述实现工作正常。但是,完成了不必要的复制。

问题:这个问题的经典解决方案是什么?

P.S。我需要两种情况都能正常工作,在第一种情况下,副本应该发生(我必须接受参数const)。在第二种情况下,不应发生任何副本。

虽然重载是可以的,但是不能选择两个独立的函数。

1 个答案:

答案 0 :(得分:2)

通过使用略有不同的原型,您可以很好地实现目标:

void filter(const shared_ptr_of_points & input, shared_ptr_of_points & output)

如果您愿意使用它,那么可能的实现将如下所示:

// Example program
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <algorithm>

typedef std::shared_ptr<std::vector<int>> shared_ptr_of_points;

bool cond(int x){
    return x > 100;
}

void filterCopy(const shared_ptr_of_points & input, shared_ptr_of_points & output){
    if (!output){
        output = std::make_shared<std::vector<int>>();
    }

    for(const auto item:*input){
        if(cond(item)){
            output->push_back(item);
        }
    }
}

void filterInplace(shared_ptr_of_points & inout){
    inout->erase(std::remove_if(inout->begin(), inout->end(), [](int x){return !cond(x);}), inout->end());
}

void filter(const shared_ptr_of_points & input, shared_ptr_of_points & output){
    if (output == input)
        filterInplace(output);
    else
        filterCopy(input, output);
}

int main()
{
    shared_ptr_of_points pts = std::make_shared<std::vector<int>>();
    pts->emplace_back(100);
    pts->emplace_back(200);
    pts->emplace_back(300);

    for(const auto item:*pts){
        std::cout << item << std::endl;
    }

    std::cout << "**********" << std::endl;

    shared_ptr_of_points resCopy;
    filter(pts, resCopy);
    for(const auto item:*resCopy){
        std::cout << item << std::endl;
    }

    std::cout << "**********" << std::endl;

    filter(pts, pts);
    for(const auto item:*pts){
        std::cout << item << std::endl;
    }
}