如何在不将容器的所有权从容器中取出的情况下访问容器的unique_ptr元素(通过迭代器)?当一个迭代器获得容器中的元素时,容器的元素所有权仍然存在?如何取消引用迭代器以访问unique_ptr?这是否执行unique_ptr的隐式移动?迭代unique_ptr的容器
我发现我使用shared_ptr的很多时候我需要存储元素的容器(不是值),即使容器在概念上拥有的元素和其他代码只是希望操纵元素的容器,因为我害怕不能实际访问容器中的unique_ptr元素而没有从其中获取所有权。
任何见解?
如何在不将容器的所有权从容器中取出的情况下访问容器的unique_ptr元素(通过迭代器)?当一个迭代器获得容器中的元素时,容器的元素所有权仍然存在?如何取消引用迭代器以访问unique_ptr?这是否执行unique_ptr的隐式移动?迭代unique_ptr的容器
我发现我使用shared_ptr的很多时候我需要存储元素的容器(不是值),即使容器在概念上拥有的元素和其他代码只是希望操纵元素的容器,因为我害怕不能实际访问容器中的unique_ptr元素而没有从其中获取所有权。
任何见解?
只要您不尝试复制unique_ptr
,您就可以使用它。你必须对迭代器“加倍取消引用”以获得指针的值,就像你必须使用shared_ptr
一样。这里有一个简单的例子:
#include <vector>
#include <memory>
#include <iostream>
template <class C>
void
display(const C& c)
{
std::cout << '{';
if (!c.empty())
std::cout << *c.front();
for (auto i = std::next(c.begin()); i != c.end(); ++i)
std::cout << ", " << **i;
std::cout << "}\n";
}
int main()
{
typedef std::unique_ptr<int> Ptr;
std::vector<Ptr> v;
for (int i = 1; i <= 5; ++i)
v.push_back(Ptr(new int(i)));
display(v);
for (auto i = v.begin(); i != v.end(); ++i)
**i += 2;
display(v);
}
如果你这样做(不小心)使unique_ptr
的副本:
Ptr p = v[0];
那么你会在编译时发现。它不会导致运行时错误。您的使用案例是为什么container<unique_ptr<T>>
已建成。事情应该正常工作,如果他们不这样做,问题就出现在编译时而不是运行时。所以,编码,如果你不明白编译时错误,然后再问这个问题。
随着auto
和范围基于for循环的C++ 11这变得相对优雅:
std::vector< std::unique_ptr<YourClass>> pointers;
for(auto&& pointer : pointers) {
pointer->functionOfYourClass();
}
参考&
到std::unique_ptr
避免了复制和可以使用uniqe_ptr
而不解除引用。
有没有人知道在这种情况下使用'auto&'和'auto &&'是否有区别?此参考文献建议双&http://en.cppreference.com/w/cpp/language/range-for,似乎都编译 – austinmarton
好问题。我发现[这个链接](http://en.cppreference.com/w/cpp/language/auto)(见解释/ 1),它表明'auto &&'可能作为左值和右值取决于初始值设定项。我相应地调整了示例。 – Pascal
好的,我认为这说明了我的事情。我一直习惯于使用新的for_each函数,其lambda参数是通过值传递的元素,而不是通过引用,但是如果我想避免尝试,我想我必须为unique_ptr元素引用它复制/移动。附:如果我将迭代器解引用一次,然后参照该结果,我认为这样可以避免尝试复制?我的意思是: {for Container :: iterator it = container.begin(); it!= container.end(); it ++) { unique_ptr&element = &*it; //没有尝试复制? }' 谢谢霍华德,顺便说一句。 –
是的,我认为这应该可以正常工作。尽管你的代码中有一个额外的'&'。但编译器会告诉你在哪里。 –
你应该能够将它解引用到:blah&element = **它;我想,仍然没有副本。 (可能更有用) –