unique_ptr的临时只读副本

Edw*_*ard 10 c++ shared-ptr stdvector unique-ptr c++11

我对C++ 11的智能指针很陌生,我正试图在项目中有效地使用它们.在我的项目,我有很多的需要常量引用一个功能vectorunique_ptr,做一些关于它的计算,并把一些成果在返回参数,如下所示:

void computeCoefficients(const vector<unique_ptr<Scalar>>& roots, 
    vector<unique_ptr<Scalar>>& coeffs) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

我正在使用,unique_ptr因为调用所有这些函数的过程是对象的唯一所有者vector,而函数只是"借用"对象以便将它们作为输入读取.

现在我正在尝试编写一个函数,在vector它接收的不同子集上进行计算,为了做到这一点,它需要有不同的"版本" vector包含这些子集,以便传递到另一个函数,vector<unique_ptr<Scalar>>作为输入.但获取向量子集的唯一方法是复制它 - 这是一个问题,因为unique_ptrs无法复制.我希望代码看起来像这样:

void computeOnSet(const vector<unique_ptr<Scalar>>& set, unique_ptr<Scalar>& output) {  
    ...
}

void computeOnAllSubsets(const vector<unique_ptr<Scalar>>& set, vector<unique_ptr<Scalar>>& outputs) {
    for(int i = 0; i < input.size(); i++) {
        auto subset = vector<unique_ptr<Scalar>>(set.begin(), set.begin()+i);
        subset.insert(subset.end(), set.begin()+i+1, set.end();
        computeOnSubset(subset, outputs.at(i));
    }
}
Run Code Online (Sandbox Code Playgroud)

当然这不起作用.如果我用unique_ptrs 代替s,我可以使它工作shared_ptr,但这有两个问题:

  • 它在哲学上意味着我与该computeOnSubsets功能共享该组的所有权,而我不是; 呼叫者仍然是唯一的所有者.(我读到这shared_ptr意味着你与拥有副本的所有东西共享所有权).
  • 它会引入引用计数的开销,即使在我不需要它的地方也是如此,因为它会迫使我将所有方法的输入参数更改为vector<shared_ptr<Scalar>>.

我想做的就是制作指针的临时只读副本,其唯一目的是制作临时的只读子向量.有没有办法做到这一点?weak_ptr听起来像我需要的(非拥有临时指针),但它只能用于shared_ptr.

And*_*owl 10

我正在使用unique_ptr,因为调用所有这些函数的过程是向量中对象的唯一所有者,并且函数只是"借用"对象以便将它们作为输入读取.

由于计算函数不拥有指向的对象,只是观察它们的状态并进行计算,你应该向它们传递一个观察指针的向量(在本例中是常规的原始指针),而不是unique_ptrs 的向量.

由于computeOnAllSubsets()并且computeOnSet()不负责Scalar对象的生命周期,他们甚至不应该获得他们的所有权 - 换句话说,他们不应该获得拥有权unique_ptr.

毕竟,程序的逻辑保证了这些函数不会接收悬空引用,因为拥有函数在执行所有必要的计算之前不会破坏它的向量.您正在编写的内容直接支持:

我想做的就是制作指针的临时只读副本,其唯一目的是制作临时的只读子向量.有没有办法做到这一点?

只需将原始指针向量传递给您的计算函数即可.给定a unique_ptr,您可以通过调用成员函数来访问封装的原始指针get():

std::unique_ptr<Scalar> pS // ... initialized somehow
Scalar* pScalar = pS.get();
Run Code Online (Sandbox Code Playgroud)

作为原始指针的替代,您可以std::reference_wrapper用于调度观察引用.特别是在重构遗留代码库的过程中,原始指针用于手动内存管理,这将清楚地表明所引用对象的所有权属于其他地方.

但请注意,在Modern C++中,原始指针通常是观察指针的同义词,因此上述区别在广义上下文中并不真正有意义.其std::reference_wrapper基本用例是当您想通过引用传递对象时,通过值接受其参数的某个函数模板(std::bind()作为典型示例).

  • 参考文献怎么样,即[参考包装](http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper)?我试图避免原始指针,因为它不清楚(从类型)什么是所有权概念. (2认同)