Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何对传出引用进行编码,以便在具有唯一\u ptr的容器上进行搜索_C++_Reference_Containers_Unique Ptr - Fatal编程技术网

C++ 如何对传出引用进行编码,以便在具有唯一\u ptr的容器上进行搜索

C++ 如何对传出引用进行编码,以便在具有唯一\u ptr的容器上进行搜索,c++,reference,containers,unique-ptr,C++,Reference,Containers,Unique Ptr,我试图替换一个函数,该函数搜索指针容器,并使用unique\u ptr将找到的元素作为传出引用 下面是一个简单的示例,演示使用普通指针时的情况: bool find_ref_in_list(int n, const std::list<int*>&l, int*& element) { auto iter = find_if(l.begin(), l.end(), [n](int* x) { return (*x == n) ? tru

我试图替换一个函数,该函数搜索指针容器,并使用
unique\u ptr
将找到的元素作为传出引用

下面是一个简单的示例,演示使用普通指针时的情况:

bool find_ref_in_list(int n, const std::list<int*>&l, int*& element)
{
    auto iter = find_if(l.begin(), l.end(), [n](int* x)
    {
        return (*x == n) ? true : false;
    });

    element = *iter;

    return true;
}
在这种情况下,我不打算共享元素的所有权,因此
shared\u ptr
不是一个选项。此外,我不想获得所有权,因此
移动
操作不是一个好主意

我知道我可以简单地使用
迭代器作为传出引用,或者使用
get()
的原始指针,但我认为这会在某种程度上阻碍惟一ptr的概念

因此,问题是,是否有可能为唯一的_ptr提供传出引用,或者哪种技术是将此问题编码为唯一的_ptr的正确技术。我正在寻找一个解决方案,它不使用第三方库,如boost

我不打算共享元素的所有权,因此
shared\u ptr
不是一个选项。另外,我不想取得所有权,所以搬家不是一个好主意

当前流行的惯例是,原始指针只是一个观察者。它不参与对象的任何类型的所有权。它也不应该存储在任何可能比它指向的对象更长寿的地方。在这种情况下使用原始指针是可以的(事实上,许多人建议使用原始指针来实现这一点)。因此,无论何时在API中使用原始指针,它都应该是非所有者指针,只提供对其他人拥有的对象的访问

但是,如果您希望能够为调用方提供实际参与所有权的选项,则需要切换到
共享\u ptr
。但是根据您所说的,您只想返回一个短暂的观察者指针,所以只需使用一个原始指针

赫伯·萨特(Herb Sutter)有一篇关于这方面的好文章:


(离题) 顺便说一下,您可以直接返回
int*
而不是
bool
,而不必使用out参数。如果未找到元素,则返回
nullptr
。因此,您的函数签名将是:

int* find_ref_in_list(int n, const std::list<int*>&l);
int*在列表中查找引用(int n,const std::list&l);
因此,问题是,是否有可能为唯一的_ptr提供传出引用,或者哪种技术是将此问题编码为唯一的_ptr的正确技术

你发明了自己的术语
外向参考
,并用它愚弄自己。您的代码中没有
传出引用
,只需通过引用返回。返回值时,如果不失去所有权,则无法返回
std::unique_ptr
。要返回引用,必须将其用作返回值,例如:

int*& find_ref_in_list(int n, const std::list<int*>&l, bool &found)
int*&在列表中查找引用(int n,const std::list&l,bool&found)
但现在您有了不同的问题,当找不到项并且函数使用困难时,返回什么。无法通过参数返回引用,因为不存在对引用的引用。因此,如果您想共享所有权,可以按值返回原始指针,或者
std::shared_ptr
。在发明自己的术语时要小心,否则你就无法理解那里到底发生了什么。

element = *iter; // causes error because assignment operator=
您试图不使引用
元素
指向
*iter
,而是分配引用的内容(在您的情况下为std::unique_ptr)。顺便说一句,
const
也有一个问题

有两种可能的解决办法:

  • 通过指针将元素传递到唯一的\u ptr:

  • 您必须检查std::find_if语句的返回值。返回值iter==l.end()
    表示搜索失败,函数可能返回false。如果迭代器有效,则应重置元素以获取新的所有权,函数可通过返回true终止

    bool find_ref_in_list(int n, const std::list<std::unique_ptr<int>>&l, std::unique_ptr<int>& element)
    {
        auto iter = std::find_if(l.begin(), l.end(), [n](const std::unique_ptr<int>& x)
        {
            return (*x == n) ? true : false;
        });
    
        if (iter == l.end()){
          element.reset(nullptr);
          return false;
        }
        element.reset(iter->get());  
        return true;
    }
    
    bool find_ref_in_list(int n,const std::list&l,std::unique_ptr&element)
    {
    自动iter=std::find_if(l.begin(),l.end(),[n](const std::unique_ptr&x)
    {
    返回(*x==n)?真:假;
    });
    如果(iter==l.end()){
    元素重置(空PTR);
    返回false;
    }
    元素重置(iter->get());
    返回true;
    }
    
    返回(*x==n)?真:假看起来像是代码混淆请参见此。我发现我没有添加未找到值的情况。所以实际上应该有一个
    if(iter==l.end())返回false就在元素赋值之前。尝试
    元素.reset(iter->get())代替
    元素=*iter@seccpur实际上这是一个很好的方法。也许你更应该把它作为一个答案而不是一个评论,因为它确实满足了所有的要求。你用
    std::reference\u wrapper
    的解决方案就是我搜索的,但是我认为不可能为这种类型声明一个变量。以下代码失败:
    std::reference\u包装器元素如果你找不到元素,你会返回什么样的引用?我在回答中已经提到了这个问题。例如,您必须抛出一个异常。我并没有说这是一个好的解决方案,我只是把它看作是一个可行的解决方案。但你最好不要那样做。关键是,在您的情况下,您并没有传出引用,您只是使用引用作为一种机制返回值。当您返回指向
    int
    的值类型指针时,您很好,当您尝试返回类型
    std::unique\u ptr
    的值时,您有明显的问题。在未找到项的情况下直接返回
    int*
    nullptr
    std::optional
    @Slava yes更简单。我想得太多了:-)对不起。当你把它作为一个评论贴在上面时,我对这个方法很满意,因此建议你把它作为一个答案贴在上面。然而
        bool find_ref_in_list(int n, const std::list<std::unique_ptr<int>>&l, const std::unique_ptr<int>* element)
        {
            auto iter = std::find_if(l.begin(), l.end(), [n](const std::unique_ptr<int>& x)
            {
                return (*x == n) ? true : false;
            });
    
            element = &*iter;
    
            return true;
        }
    
    bool find_ref_in_list(int n, const std::list<std::unique_ptr<int>>&l, std::reference_wrapper<const std::unique_ptr<int>>& element)
    {
        auto iter = std::find_if(l.begin(), l.end(), [n](const std::unique_ptr<int>& x)
        {
            return (*x == n) ? true : false;
        });
    
        element = std::ref(*iter);
    
        return true;
    } 
    
    bool find_ref_in_list(int n, const std::list<std::unique_ptr<int>>&l, std::unique_ptr<int>& element)
    {
        auto iter = std::find_if(l.begin(), l.end(), [n](const std::unique_ptr<int>& x)
        {
            return (*x == n) ? true : false;
        });
    
        if (iter == l.end()){
          element.reset(nullptr);
          return false;
        }
        element.reset(iter->get());  
        return true;
    }