我对C ++ 11的智能指针很陌生,我正试图在项目中有效地使用它们。在我的项目中,我有很多函数对vector
的{{1}}进行const引用,对它进行一些计算,并将一些结果放在一个返回参数中,如下所示:
unique_ptr
我正在使用void computeCoefficients(const vector<unique_ptr<Scalar>>& roots,
vector<unique_ptr<Scalar>>& coeffs) {
...
}
,因为调用所有这些函数的过程是unique_ptr
中对象的唯一所有者,而函数只是“借用”对象以便将它们读取为输入。
现在我正在尝试编写一个函数来对它收到的vector
的不同子集进行计算,为了做到这一点,它需要包含vector
的不同“版本”这些子集是为了传递给另一个以vector
作为输入的函数。但获取向量子集的唯一方法是复制它 - 这是一个问题,因为vector<unique_ptr<Scalar>>
s无法复制。我希望代码看起来像这样:
unique_ptr
当然这不起作用。如果我用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));
}
}
替换unique_ptr
s,我可以使它工作,但这有两个问题:
shared_ptr
函数共享集合的所有权,而我不是;呼叫者仍然是唯一的所有者。 (我读到computeOnSubsets
表示你与拥有副本的所有内容共享所有权。)shared_ptr
。 我想做的只是制作指针的临时,只读副本,其唯一目的是制作临时,只读子向量。有没有办法做到这一点? vector<shared_ptr<Scalar>>
听起来像我需要的(非拥有临时指针),但它只能与weak_ptr
一起使用。
答案 0 :(得分:10)
我正在使用unique_ptr,因为调用所有这些函数的过程是向量中对象的唯一所有者,而函数只是“借用”对象以便将它们作为输入读取。
由于计算函数不拥有指向的对象,只需观察它们的状态并进行计算,你应该向它们传递一个观察指针的向量(在这种情况下,常规原始指针< / strong>),而不是unique_ptr
s的向量。
由于computeOnAllSubsets()
和computeOnSet()
不对Scalar
个对象的生命周期负责,因此他们甚至不应获得所有权 - 换句话说,他们不应该获得拥有权unique_ptr
1}}秒。
毕竟,程序逻辑保证这些函数不会接收悬空引用,因为拥有函数在执行所有必要的计算之前不会破坏它的向量。您正在编写的内容直接支持:
我想要做的只是制作指针的临时只读副本,其唯一目的是制作临时的只读子向量。有没有办法做到这一点?
只需将原始指针向量传递给您的计算函数。给定unique_ptr
,您可以通过调用成员函数get()
来访问封装的原始指针:
std::unique_ptr<Scalar> pS // ... initialized somehow
Scalar* pScalar = pS.get();
作为原始指针的替代方法,您可以使用std::reference_wrapper
来分派观察引用。特别是在重构遗留代码库的过程中,其中原始指针用于手动内存管理,这将清楚地表明所引用对象的所有权属于其他地方。
但请注意,在Modern C ++中,原始指针通常是观察指针的同义词,因此上述区别在广义上下文中并不真正有意义。 std::reference_wrapper
是基础的用例是当您想要通过引用传递对象时,通过值接受其参数的某个函数模板(std::bind()
是一个典型示例)。
答案 1 :(得分:2)
使用迭代器可能会使您的代码更加通用。只需声明你的计算函数:
template <typename InputIt, typename OutputIt>
void compute(InputIt first_it, InputIt last_it, OutputIt d_first, Output d_last);
此计算函数模板处理范围[first_it, last_it)
中的数据,然后将结果放入[d_first, d_last)
。它不关心输入或输出容器的类型。迭代器充当容器中元素的指针,这是STL的想法。
此外,在某些情况下,您甚至不会手动浏览范围。只需使用<algorithm>
中的功能模板,例如std::for_each
和std::transform
。
我真的不理解computeOnAllSubsets
中的代码段,但我本能地认为std::transform
可能会有帮助。