2

std::shared_ptr::operator* 通过左值引用返回,这里给出的重载指针类操作的答案说约定是通过左值引用返回。但是,当我使用以下代码时,我收到错误 C2664: 'AdjacencyList::addVertex' : cannot convert parameter 1 from 'AdjacencyList::vertex_type' to 'AdjacencyList::vertex_type &&': You cannot bind an lvalue to an右值参考:

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& v) 还是更改上述块底部的代码以在传递给 addVertex 之前复制顶点?

AdjacencyList minimumSpanningTree;
Vertex s(*startVertex);
const auto mstStartVertex(minimumSpanningTree.addVertex(std::move(s)));
4

2 回答 2

2

我认为您应该从您的 中返回一份副本operator*,因为该语义std::weak_ptr表明您不能保证返回的参考将保持有效。由于返回的副本随后被提供给可以将其移动到其他地方的函数,因此它也应该足够高效,因为addVertex看起来它无论如何都需要一个副本,即,如果您创建 的重载addVertex,它将创建 的副本内部传递的 const 引用,会吗?

于 2013-04-10T05:23:15.540 回答
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}));

但是,在这种情况下,您不妨在调用本身中创建临时值,方法是提供单个值重载(如何在添加新的 c++0x 右值引用运算符重载时减少冗余代码):

std::shared_ptr<vertex_type> AdjacencyList::addVertex(vertex_type);
于 2013-04-10T09:51:02.833 回答