std :: shared_ptr :: operator *通过左值引用返回,并且重载指针(如操作here)给出的答案表示约定是通过左值引用返回的。但是,当我使用以下代码时,我得到错误C2664:'AdjacencyList :: addVertex':无法将参数1从'AdjacencyList :: vertex_type'转换为'AdjacencyList :: vertex_type&&':您无法绑定左值参考的左值:
std::shared_ptr<vertex_type> AdjacencyList::addVertex(vertex_type&& v)
{
auto existingVertex(findVertex(v));
if (!existingVertex.isValid())
{
existingVertex = std::make_shared<vertex_type>(std::forward<vertex_type>(v))
m_vertices.push_back(existingVertex);
}
return existingVertex;
};
AdjacencyList minimumSpanningTree;
// startVertex is a shared_ptr to a vertex returned from a previous call of addVertex
// on another AdjacencyList object
const auto mstStartVertex(minimumSpanningTree.addVertex(*startVertex));
我应该提供AdjacencyList :: addVertex(const vertex_type&amp; v)还是更改上面块底部的代码,以便在传递给addVertex之前复制顶点?
AdjacencyList minimumSpanningTree;
Vertex s(*startVertex);
const auto mstStartVertex(minimumSpanningTree.addVertex(std::move(s)));
答案 0 :(得分:2)
我认为您应该从operator*
返回副本,因为std::weak_ptr
的语义表明您不能保证返回的引用保持有效。由于返回的副本随后被赋予可以将其移动到其他地方的函数,因此它也应该足够有效,因为addVertex
看起来无论如何都需要副本,即,如果你将创建addVertex
的重载,它将在内部创建传递的const引用的副本,是吗?
答案 1 :(得分:1)
就冗余副本而言,最有效的方法是提供rvalue和const引用重载:
std::shared_ptr<vertex_type> AdjacencyList::addVertex(vertex_type&&);
std::shared_ptr<vertex_type> AdjacencyList::addVertex(const vertex_type&);
要消除冗余代码,您可以转发模板方法或采用bool
标记并在适当时执行const_cast
的具体方法。
如果复制Vertex
对象的开销与增加代码的成本相比最小,并且通常或经常输入if
块,则冗余副本将使您的代码更清晰。如果您只是创建一个不需要移动的prvalue临时值,那么您的第二个建议调用将会更好:
const auto mstStartVertex(minimumSpanningTree.addVertex(Vertex{*startVertex}));
但是在这种情况下,您也可以通过提供单个值重载(How to reduce redundant code when adding new c++0x rvalue reference operator overloads)来在调用本身中创建临时值:
std::shared_ptr<vertex_type> AdjacencyList::addVertex(vertex_type);