C++ 防止在返回时复制共享指针

C++ 防止在返回时复制共享指针,c++,shared-ptr,return-value-optimization,C++,Shared Ptr,Return Value Optimization,我有一个从std::map派生的容器,它保存共享指针,还有一个用于查找元素的自定义方法,类似于下面的代码 容器在我使用它时不会改变,我希望查找返回共享指针而不进行复制,并且不增加指针的计数器。我如何确保这一点 struct X; using Xp = std::shared_ptr< X >; struct Xs : std::map< int, Xp > { Xp get( int n ) const { auto p = find( n );

我有一个从
std::map
派生的容器,它保存共享指针,还有一个用于查找元素的自定义方法,类似于下面的代码

容器在我使用它时不会改变,我希望查找返回共享指针而不进行复制,并且不增加指针的计数器。我如何确保这一点

struct X;    
using Xp = std::shared_ptr< X >;

struct Xs : std::map< int, Xp >
{
  Xp get( int n ) const {
    auto p = find( n );
    return p != end() ? p->second : nullptr;
  }
};

Xs xs;

void test() {
  // always increments the counter of the shared_ptr :(
  if( auto const& p = xs.get( 5 ) )
    ( void ) p;
}
structx;
使用Xp=std::shared_ptr;
结构Xs:std::map
{
Xp获取(整数n)常量{
自动p=查找(n);
返回p!=end()?p->second:nullptr;
}
};
Xs-Xs;
无效测试(){
//始终递增共享ptr的计数器:(
if(auto const&p=xs.get(5))
(无效)p;
}

编辑:我无法更改容器,也无法返回原始指针。在不更改指针的情况下,是否无法返回指针的引用?

您可以使用null对象来允许返回引用:

struct Xs : std::map< int, Xp >
{
  const Xp& get( int n ) const {
    static const Xp nullObject{nullptr};
    auto p = find( n );
    return p != end() ? p->second : nullObject;
  }
};
结构Xs:std::map { 常量Xp和get(int n)常量{ 静态常量Xp nullObject{nullptr}; 自动p=查找(n); 返回p!=end()?p->second:nullObject; } };
您可以使用null对象来允许返回引用:

struct Xs : std::map< int, Xp >
{
  const Xp& get( int n ) const {
    static const Xp nullObject{nullptr};
    auto p = find( n );
    return p != end() ? p->second : nullObject;
  }
};
结构Xs:std::map { 常量Xp和get(int n)常量{ 静态常量Xp nullObject{nullptr}; 自动p=查找(n); 返回p!=end()?p->second:nullObject; } };
并且不要增加指针的计数器
智能指针就是这样做的,否则您可能应该使用原始指针。为什么不制作共享指针的副本呢?这就是它的要点,您可以有许多不同的共享指针副本,但它们都指向同一个对象。您的问题,正如它所说是现在,有一种明显的气味。@Someprogrammerdude如果你不存储副本,这是毫无意义的。这是一个公平的问题。你可以返回一个
std::weak_ptr
std::weak_ptr
肯定是正确的答案。如果你不打算添加额外的所有权,这就是
std::weak_ptr
存在的原因。
并且不要增加指针的计数器
智能指针就是这样做的,否则您可能应该使用原始指针。为什么不复制共享指针呢?这就是问题的关键,您可以有许多不同的共享指针副本,但它们都指向同一个对象。您的问题是正确的现在,它有一种明显的气味。@Someprogrammerdude如果你不存储副本,它是毫无意义的。这是一个公平的问题。你可以返回一个
std::weak_ptr
std::weak_ptr
肯定是正确的答案。如果你不打算添加额外的所有权,这就是
std::weak_ptr
存在的原因。