如何正确使用std :: bind与std :: unique_ptr

时间:2019-06-06 06:07:05

标签: c++11 unique-ptr member stdbind

我正在尝试结合std::bindstd::unique_ptr个类函数,但要使其正常工作会遇到很多麻烦

首先我有两个课

class simpleClass{
    public:
        simpleClass(int x){
            this->simpleNumber = x;
        }

        int simpleNumber;

        simpleClass(const simpleClass &toBeClone){
            this->simpleNumber = toBeClone.simpleNumber;
        }
        simpleClass clone(){
            simpleClass *cloned = new simpleClass(*this);
            return *cloned;
        }
};
class   className{
    public:
        className(doube input){
            this->someVariable = input;
        }

        void someFunction(std::vector<double> x, double c, std::unique_ptr<simpleClass> &inputClass, std::vector<double> &output){
            std::vector<double> tempOutput;
            for(int i = 0; i<x.size(); i++){
                tempOutput.push_back(x[i] + c * this->someVariable + inputClass->simpleNumber);
            }
            output = tempOutput;
        }

        double someVariable;

        className(const className &toBeClone){
            this->someVariable = toBeClone.someVariable;
        }

        className clone(){
            className *cloned = new className(*this);
            return *cloned;
        }
};

它们都是一些标准类,但是我还实现了一个克隆函数来复制已初始化的类。克隆时,我需要确保原始类和克隆的类指向不同的地址。因此,我使用std::unique_ptr来确保这一点。

这是主要功能,它也显示了我如何“克隆”

int main(){
    className testSubject(5);
    std::vector<std::unique_ptr<className>> lotsOfTestSubject;

    simpleClass easyClass(1);
    std::vector<std::unique_ptr<simpleClass>> manyEasyClass;


    for(int i = 0; i<10; i++){
        std::unique_ptr<className> tempClass(new className(testSubject.clone()))
        lotsOfTestSubject.push_back(std::move(tempClass));    

        std::unique_ptr<simpleClass> tempEasyClass(new simpleClass(easyClass.clone()))
        manyEasyClass.push_back(std::move(tempEasyClass));    
    }

    std::vector<std::vector<<double>> X; //already loaded with numbers
    double C = 2;
    std::vector<std::vector<<double>> OUT;

    for(int i = 0; i<10; i++){
        std::vector<double> tempOUT;
        lotsOfTestSubject[i]->someFunction(X[i], C, manyEasyClass[i], tempOUT);
        OUT.push_back(tempOUT);

        //Here if I want to bind
        /*
           std::bind(&className::someFunction, lotsOfTestSubject[i], X[i], C, manyEasyClass[i], tempOUT);
        */
    }
    return 0;
}

我之所以“克隆”是因为simpleClassclassName都需要花很多时间来构造我的实现,而我需要很多。而且由于其中许多将使用相同的参数进行初始化,所以我认为这是最简单的方法。

上面的代码有效,但是我正在尝试提高循环速度。下一行是大部分计算发生的地方。

lotsOfTestSubject[i]->someFunction(X[i], C, manyEasyClass[i], tempOUT);

因此,我正在尝试使用线程来委派工作,据我所知,我需要首先std::bind。所以我尝试了

std::bind(&className::someFunction, lotsOfTestSubject[i], X[i], C, manyEasyClass[i], tempOUT);

但是编译器会打印出这样的错误

/usr/include/c++/5/tuple|206|  recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 1ul; _Head = std::vector<double>; _Tail = {double, std::unique_ptr<simpleClass, std::default_delete<simpleClass> >, std::unique_ptr<simpleClass, std::default_delete<simpleClass> >, std::vector<double>}]’|
/usr/include/c++/5/tuple|108|error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = className; _Dp = std::default_delete<className>]’|

我不知道这是什么意思,因为我刚开始自学c ++。非常感谢任何反馈和指导。 我正在使用c ++ 11和g ++(Ubuntu 5.4.0-6ubuntu1〜16.04.11)5.4.0 20160609

更新

感谢@ rafix07,尝试了您的解决方案,它正常工作。但后来我尝试做

auto theBinded = std::bind(&className::someFunction, &lotsOfTestSubject[i], 
          X[i], C, std::ref(manyEasyClass[i]), tempOUT);
std::thread testThread(theBinded);

,最终想testThread.join() 但是编译器说

error: pointer to member type ‘void (className::)(std::vector<double>, double, std::unique_ptr<simpleClass>&, std::vector<double>&)’ incompatible with object type ‘std::unique_ptr<className>’|

@kmdreko谢谢您指出!我还没有注意到内存泄漏,但是我会修复。我只用这个吗?

std::unique_ptr<className> tempClass = new className(testSubject);

1 个答案:

答案 0 :(得分:1)

编辑

如果要对存储在someFunction中的实例调用lotsOfTestSubject,则需要将指针传递到将在其上调用此方法的className对象,因此下面的行

std::bind(&className::someFunction, lotsOfTestSubject[i]

应替换为:

auto theBinded = std::bind(&className::someFunction, lotsOfTestSubject[i].get(), 
                                                                          ^^^          

第二个更改是使用std::ref传递unique_ptr的{​​{1}}的原始实例,而不是其副本。 manyEasyClass总是复制或移动其参数(see reference),但是std::bind是不可复制的,这就是编译失败的原因。

所以固定线看起来:

unique_ptr

auto theBinded = std::bind(&className::someFunction, lotsOfTestSubject[i].get(), X[i], C, std::ref(manyEasyClass[i]), std::ref(tempOUT)); 也必须由tempOUT传递,因为您想在std::ref创建的函子上通过调用operator()来修改此向量。

LIVE DEMO