从std :: for_each + lambda函数返回unique_ptr

时间:2018-04-05 04:56:47

标签: c++ vector foreach bitmap c++17

我遇到了将std :: moved unique_pointers返回到lambda的问题。一旦我将指针移动到lambda函数,我如何从lambda中取回所有权?

在下面的代码中,我正在演示我的问题。我从代码库中删除了一切并将所有内容都移到main来更好地解释问题。第一个问题被标记为“问题1” - 我想知道我是否正确使用(* v)访问我的向量。

代码创建一个数字向量,然后迭代向量以标记位图中的位。我认为这些位被正确标记,因为我能够在lambda本身中打印它们。在标记位之后,我想要归还所有权。我该怎么做?我需要将位图指针返回给调用函数。

如何从lambda以STANDARD方式取回所有权,而不是在传递的unique_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 个答案:

答案 0 :(得分:0)

  

问题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:我现在需要返回位图的所有权。怎么做?

你不能用lambda来做,在你的情况下通过引用捕获来完成工作(即使lambda拥有向量,for_each“block”也没有):

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());