如何使用右值引用包装指针



std::shared_ptr::operator*按左值引用返回,这里对重载指针类操作给出的答案是,约定是按左值引用返回。然而,当我使用以下代码时,我得到错误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&v)或改变在上面块的底部的代码,使顶点的副本传递给addVertex之前?

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

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

就冗余副本而言,最有效的方法是提供右值和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块通常或经常被输入,那么冗余复制将使您的代码更清晰。你的第二个建议调用将更好地工作,如果你只是创建一个不需要移动的右值临时:

const auto mstStartVertex(minimumSpanningTree.addVertex(Vertex{*startVertex}));

然而,在这种情况下,您不妨通过提供单值重载(如何在添加新的c++0x右值引用操作符重载时减少冗余代码)在调用本身中创建临时对象:

std::shared_ptr<vertex_type> AdjacencyList::addVertex(vertex_type);

最新更新