从std :: for_each lambda函数返回unique_ptr

Returning unique_ptr from std::for_each + lambda functions

本文关键字:返回 ptr unique 函数 each std for lambda      更新时间:2023-10-16

我正面临返回std ::移动unique_pointers到lambda的问题。一旦我将指针移至lambda函数,我该如何从lambda中夺回所有权?

在以下代码中,我正在证明我的问题。我已经从代码库中脱掉了一个抢断,并将所有内容移到了主要方面,以更好地解释问题。第一个问题被标记为"问题1" - 我想了解我是否正确使用(*v(访问矢量。

是正确的。

代码创建一个数字很少的向量,然后在向量上迭代以标记位图中的位。我认为这些位是正确标记的,因为我能够在lambda本身中打印它们。在标记位后,我希望所有权返回。我该怎么做?我需要将位图指针返回到呼叫者函数。

如何以标准方式从lambda中恢复所有权,而不是围绕传递的唯一_ptr入侵或避免将指针移至lambda。CPP17是否支持此?

用G -STD = C 17

编译代码
#include <memory>
#include <algorithm>
#include <iostream>
#include <vector>
int main () {
  int increments = 10;
  int numberOfElements = 10;
  /* Create the vector */
  auto v = std::make_unique<std::vector<int>>(std::vector<int> (numberOfElements));
  /* QUESTION 1 - is (*v) the right way to access it or there is a better way. */
  std::generate((*v).begin(), (*v).end(), [n=0, increments]() mutable { n = n + increments; return n;});
  /* Print the generated elements */
  std::cout << "nPrinting the generated elements ";
  std::for_each((*v).begin(), (*v).end(), [](int n) { std::cout<<" " << n;});

  /* Int find the maximum element */
  int maxElement = *(std::max_element((*v).begin(), (*v).end()));
  /* Making a bitmap of the elements */
  std::cout << "nPrinting the maxElement " << maxElement;
  auto bitmap = std::make_unique<std::vector <bool>> (std::vector<bool>(maxElement + 1));
  /* Now setting all the elements in the vector to true in the bitmap. */
  for_each((*v).begin(), (*v).end(), [bmap = std::move(bitmap)](int n) { 
                                        (*bmap).at(n) = true; 
                                        if ((*bmap).at(n) == true) { 
                                          std::cout << "nBit "<< n <<" marked";
                                        }
                                      });
  /******************************************************* 
   * Question 2 : I now need the ownership of bitmap back.
   * How to do it ?. Bitmap is now null after moving it to the lambda.
   */
  if (bitmap) {
    std::cout << "nafter reset, ptr is not NULL ";
  } else if (bitmap == nullptr) {
    std::cout << "nbitmap is null";
  }
}

问题1-是(*v(访问它或有更好的方法的正确方法。

替代方法是使用->,因此v->begin()代替(*v).begin()。但是将unique_ptr用于vector很奇怪。您可能只是做:

std::vector<int> v(numberOfElements);
std::generate(v.begin(), v.end(),
              [n=0, increments]() mutable { n = n + increments; return n;});
std::cout << "nPrinting the generated elements ";
for (int e : v) { std::cout << " " << e; };
int maxElement = *std::max_element(v.begin(), v.end());
// ...

问题2:我现在需要Bitmap的所有权。如何做?

您不能使用lambda做到这一点,在您的情况下,通过参考来捕获工作(即使lambda将拥有向量,for_each"块"不(:

std::vector<bool> bitmap(maxElement + 1);
for_each(v.begin(), v.end(), [&bmap](int n) { 
                                 bmap.at(n) = true;
                                 std::cout << "nBit "<< n <<" marked";
                             });
assert(!bitmap.empty());
if (bitmap.empty()) {
    std::cout << "nbitmap is empty";
} else if (bitmap == nullptr) {
    std::cout << "nbitmap is NOT empty";
}

如果您用自己的函子替换lambda,则可以做

之类的事情
class MyMarker
{
public:
    MyMarker(std::vector<bool>&& bitmap) : bitmap(std::move(bitmap)) {}
    MyMarker(const MyMarker&) = delete;
    MyMarker& operator =(const MyMarker&) = delete;
    void operator() (int n) const
    {
        bitmap.at(n) = true;
        std::cout << "nBit "<< n <<" marked";
    }
    std::vector<bool> TakeBack() { return std::move(bitmap); }
private:
    std::vector<bool> bitmap;
};

,然后:

std::vector<bool> bitmap(maxElement + 1);
MyMarker myMarker(std::move(bitmap));
assert(bitmap.empty());
std::for_each(v.begin(), v.end(), myMarker);
bitmap = myMarker.TakeBack();
assert(!bitmap.empty());