如何创建 class 的唯一指针向量

How to create a vector of unique pointers of a class

我正在查看使用 new 和 delete 为 类 创建指针的代码,我正在尝试更新代码以使用唯一指针。这是我的代码。

#include <iostream>
#include <memory>
#include <vector>

class Algorithm
{
    private:
    public:
        virtual void runn_algo() = 0;
        virtual ~Algorithm() {};
};

class Algo1 : public Algorithm
{
        void runn_algo()
        {
                std::cout << "running Algo1" << std::endl;
        }
};

class Algo2 : public Algorithm
{
        void runn_algo()
        {
                std::cout << "running Algo2" << std::endl;
        }
};

class runner
{
    public:
        void runn_algo(std::unique_ptr<Algorithm> upa)
        {
                upa->runn_algo();
        }
};

int main()
{
        std::vector<std::unique_ptr<Algorithm>> algos;

        algos.emplace_back(std::make_unique<Algo1>());
        algos.emplace_back(std::make_unique<Algo1>());
        algos.emplace_back(std::make_unique<Algo2>());

        runner run;

        for (auto i = 0u; i < algos.size(); ++i)
        {
                run.runn_algo(algos[i]);
        }
}

我收到以下错误:

call to implicitly-deleted copy constructor of 'std::unique_ptr<Algorithm>'
                run.runn_algo(algos[i]);

我不确定为什么会这样。带有原始指针的代码工作正常

class runner
{
    public:
        void runn_algo(Algorithm* upa)
        {
                upa->runn_algo();
        }
};

int main()
{
        std::vector<Algorithm*> algos;

        algos.push_back(new Algo1());
        algos.push_back(new Algo1());
        algos.push_back(new Algo2());

        runner run;

        for (auto i = 0u; i < algos.size(); ++i)
        {
                run.runn_algo(algos[i]);
        }
}

如错误消息所示,unique_ptr 没有复制构造函数,因此不能按值传递给函数。您可以更改签名以接受 const std::unique_ptr<Algorithm>& 引用:

class runner
{
public:
    void runn_algo(const std::unique_ptr<Algorithm>& upa)
    {
        upa->runn_algo();
    }
};

产生输出

running Algo1
running Algo1
running Algo2

符合预期。

或者,以不关心 Algorithm 存储方式的方式编写 runner::runn_algo

class runner
{
public:
    void runn_algo(Algorithm& algo)
    {
        algo.runn_algo();
    }
};

int main()
{
    std::vector<std::unique_ptr<Algorithm>> algos;

    algos.emplace_back(std::make_unique<Algo1>());
    algos.emplace_back(std::make_unique<Algo1>());
    algos.emplace_back(std::make_unique<Algo2>());

    runner run;

    for (auto i = 0u; i < algos.size(); ++i)
    {
        run.runn_algo(*algos[i]); // Dereference operator on algos[i]
    }
}

首先,您的 emplace_back 实际上应该是 push_back,因为您使用的是 make_unique

algos.push_back(std::make_unique<Algo1>());
algos.push_back(std::make_unique<Algo1>());
algos.push_back(std::make_unique<Algo2>());

其次你应该使用 virtualoverride 让你的方法多态

virtual void runn_algo();  // base
void runn_algo() override; // derived

第三,您可能应该将参数作为原始(非拥有)指针传递给您的 runner,因为如果您尝试按值传递 unique_ptr,它会尝试复制,这unique_ptr

不允许
void runn_algo(std::unique_ptr<Algorithm> alg);  // nope, cannot copy
void runn_algo(Algorithm* alg);                  // ok, non-owning

for (auto i = 0u; i < algos.size(); ++i)
{
    run.runn_algo(algos[i].get());               // access underlying pointer
}

虽然在这种情况下,我真的不明白 runner 的意义,因为您可以在这里使用多态性

for (auto& alg : algos)
{
    alg->run_algo();  // will be polymorphic
}