C++ lambda函数引用传递问题

C++ lambda function pass by reference problem

我使用 lambda 函数将点云存储到向量的每个实例中。即使我通过引用传递向量,当我尝试访问向量的每个实例时,我也会收到此错误:

typename boost::detail::sp_member_access<T>::type boost::shared_ptr<T>::operator->() const [with T = pcl::PointCloud<pcl::PointXYZI>; typename boost::detail::sp_member_access<T>::type = pcl::PointCloud<pcl::PointXYZI>*]: Assertion `px != 0' failed.

我的代码:

int size_ = 2;
std::vector<Cloud::Ptr> vector_cloud(size_);
for(int i=0; i<size_; i++)
{
    Cloud::Ptr cloud_(new Cloud);
    vector_cloud.push_back(cloud_);
}
auto fonk1 = [ &vector_cloud, size_]()
        {

            for(int i=0; i<size_; i++)
            {
                std::cout << "for debug" << std::endl;
                Point p;
                p.x = 0;
                p.y = 0;
                p.z = 0;
                p.intensity = 0;
                vector_cloud[i]->points.push_back(p);
            }
        };
fonk1();
std::cout << "Cloud size: " << vector_cloud[0]->size() << std::endl;

不是编译错误,输出为:

for debug

当我尝试推送一个点时出现此错误。 Cloud::Ptrpcl::PointCloud<pcl::pointXYZI>::PtrPointpcl::PointXYZI

我什至删除了那些行:

    for (int i=0; i<2; i++) {
    Cloud::Ptr cloud(new Cloud);
    vector_cloud_frustums.push_back(cloud);
}

错误是一样的。

我假设 PointCloudCloud::Ptr 是这样的:

struct Point {
    int x,y,z,intensity;
};

struct Cloud {
    std::vector<Point> points;
    void push_back(const Point& p) { points.push_back(p);}
    using Ptr = Cloud*;
    size_t size() const { return points.size(); }
};

事实证明它们是另外一回事,但这对答案来说并不重要。


您的代码中的问题是您创建了一个大小为 2 的向量:

std::vector<Cloud::Ptr> vector_cloud(size_);

然后在这个循环中再压入 2 个元素:

for(int i=0; i<size_; i++)
{
    Cloud::Ptr cloud_(new Cloud);
    vector_cloud.push_back(cloud_);
}

前两个元素不指向 Cloud 的实例。只有最后两个指向 Cloud。然后在你代码的最后一行:

std::cout << "Cloud size: " << vector_cloud[0]->size() << std::endl;

您取消引用向量中的第一个元素并导致未定义的行为。可以在这个complete example.

中看到效果

结论:您的代码中的问题不是 lambda 或捕获向量。坏线是最后一条。它调用未定义的行为。在上面的 link 中,您可以取消注释该行以查看它如何影响其余代码的作用(即使其他代码出现在前面)。

解决方法是预先创建大小为 2 的向量,然后使用 使用 push_back 访问这些元素,但不能同时访问这两个元素。例如:

int size_ = 2;
std::vector<Cloud::Ptr> vector_cloud;  // empty vector !!
vector_cloud.reserve(size_);           // reserve space
for(int i=0; i<size_; i++)
{
    Cloud::Ptr cloud_(new Cloud);
    vector_cloud.push_back(cloud_);    // push elements
}

PS 您很可能不需要代码中的任何指针。使用 std::vector<Cloud> 而不是 std::vector<Cloud*>,除非有理由引入间接级别。当有的时候,使用智能指针。