简体   繁体   中英

C++ lambda function pass by reference problem

I used a lambda function in order to store point cloud into each instance of a vector. Even I pass the vector by reference, when I try to access each instance of the vector, I get this error:

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.

My codes:

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;

It's not a compiling error, and output is:

for debug

I get this error, when I try to push a point. Cloud::Ptr is pcl::PointCloud<pcl::pointXYZI>::Ptr and Point is pcl::PointXYZI

Also even I delete those lines:

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

Error is the same.

I assume Point , Cloud and Cloud::Ptr are something like this:

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

It turned out they are something else, but that doesnt matter that much for the answer.


The issue in your code is that you create a vector of size 2:

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

Then you push 2 more elements in this loop:

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

The first two elements do not point to instances of Cloud . Only the last two point to a Cloud . Then in the last line of your code:

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

You dereference the first element in the vector and cause undefined behavior. You can see the effect in this complete example .

Conclusion: The problem in your code is not the lambda or capturing the vector. The bad line is the last one. It invokes undefined behavior. In the above link you can uncomment that line to see how it effects what the rest of the code does (even if that other code comes before).

The fix is to either create vector with size 2 upfront and then access those element or use push_back , but not both. For example:

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 Very likely you do not need any pointers in the code. Use a std::vector<Cloud> instead of a std::vector<Cloud*> , unless there is a reason to introduce a level of indirection. And when there is, use smart pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM