Ask Your Question
18

What is ConstPtr&?

asked 2015-07-03 14:02:45 -0600

OmoNaija gravatar image

updated 2015-07-03 14:36:57 -0600

Hey All, I'm still new to ROS and C++. I'm having trouble understanding what the ConstPtr& does when writing the callback function for a simple subscriber:

 void chatterCallback(const std_msgs::String::ConstPtr& msg) 

     {ROS_INFO("I heard: [%s]", msg->data.c_str());}

Wouldn't the code work with just:

 void chatterCallback(const std_msgs::String msg)

      {ROS_INFO("I heard: [%s]", msg);}
edit retag flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted
30

answered 2015-07-04 01:05:17 -0600

fergs gravatar image

updated 2018-11-10 13:11:15 -0600

ahendrix gravatar image

When messages are automatically generated into C++ code, there are several typedefs defined. One of them is ::Ptr, which is typedef-ed to be a boost::shared_ptr<MSG>, and another is ::ConstPtr which is boost::shared_ptr<MSG const>.

By passing a const pointer into the callback, we avoid doing a copy. While this might not make much difference for std_msgs::String, it can make a huge difference for sensor_msgs::PointCloud2.

edit flag offensive delete link more

Comments

Thank You!

OmoNaija gravatar image OmoNaija  ( 2015-07-06 14:28:54 -0600 )edit

thanks a lot for your help

feixiao gravatar image feixiao  ( 2016-01-21 21:57:54 -0600 )edit

but what does & means? If msg is already a pointer, why do we take the address of msg? Or does that & means passing by reference?

wy3 gravatar image wy3  ( 2017-07-29 15:27:13 -0600 )edit
4

@wy3: the ampersand (&) means pass by reference as you said.

ksirks gravatar image ksirks  ( 2017-09-15 10:47:56 -0600 )edit

Note: today I think boost::shared_ptr<> is replaced in ROS by std::shared_ptr<>, since this is now part of the C++ Standard Library.

eRCaGuy gravatar image eRCaGuy  ( 2020-06-10 14:40:22 -0600 )edit
1

@wy3, the & is to pass the shared_ptr object itself by reference. The shared_ptr object is a class which manages the object it wraps and "points to", and the & is to pass the shared_ptr object by reference. So, we are passing a message by a reference to a smart pointer which points to it--yeah, it's kind of a double-layered approach. In C you'd just pass the message by pointer and be done, but the added benefit of using a shared pointer, which is a type of "smart pointer", is that it automatically manages the storage duration of the memory (for the message) it points to, meaning you never have to manually free or delete this dynamically-allocated memory block for the message because it's done automatically when all shared pointers to that memory are gone or out of scope.

eRCaGuy gravatar image eRCaGuy  ( 2020-06-10 14:47:18 -0600 )edit

I just added my above comments, and more, into my own answer here. I realized my comments were becoming more than just comments, so I made them into an answer.

eRCaGuy gravatar image eRCaGuy  ( 2020-06-10 15:15:18 -0600 )edit

ROS1 still very much uses boost in roscpp - changing to std::shared_ptr would break the world. ROS2 does drop boost for std::shared_ptr in rclcpp.

fergs gravatar image fergs  ( 2020-08-18 18:05:26 -0600 )edit
8

answered 2020-06-10 15:13:05 -0600

eRCaGuy gravatar image

updated 2020-06-10 15:31:36 -0600

I'd like to expound upon the main answer here.

::ConstPtr can be understood and read as "shared pointer to a constant message", and ::Ptr can be understood and read as "shared pointer to a (modifiable) message". It's just a smart-pointer-based light-weight way of passing messages. Choose the correct one based on whether or not the recipient of the passed message will need to modify the message. Read more about std::shared_ptr<>here: https://en.cppreference.com/w/cpp/mem....

Therefore, ::ConstPtr& can be understood and read as "reference to a shared pointer to a constant message", and ::Ptr& can be understood and read as "reference to a shared pointer to a (modifiable) message".

Today I think boost::shared_ptr<> is replaced in ROS by std::shared_ptr<>, since this is now part of the C++ Standard Library. See here: https://github.com/ros-planning/movei....

That means this is what these definitions would be today:

::Ptr is typedef-ed to std::shared_ptr<MSG>, which is a shared pointer to a message, and ::ConstPtr is typedef-ed to std::shared_ptr<MSG const>, which is a shared pointer to a const message.

Addressing this question in the comments under the main answer:

but what does & means? If msg is already a pointer, why do we take the address of msg? Or does that & means passing by reference?

The & is to pass the shared_ptr object itself by reference. The shared_ptr object is a class which manages the object it wraps and "points to", and the & is to pass the shared_ptr object by reference. So, we are passing a message by a reference to a smart pointer which points to it--yeah, it's kind of a double-layered approach. In C you'd just pass the message by pointer and be done, but the added benefit of using a shared pointer, which is a type of "smart pointer", is that it automatically manages the storage duration of the memory (for the message) it points to, meaning you never have to manually free or delete this dynamically-allocated memory block for the message because it's done automatically when all shared pointers to that memory are gone or out of scope.

So, passing a smart pointer saves potentially a TON of data and time in the passing of the message, and passing the smart pointer itself by reference rather than value saves a tiny bit more of data and time by not having to pass the entire smart pointer object, but rather just a reference to it. It is another small bit of savings in the message passing.

Also, I hate the names ::ConstPtr and ::Ptr. They create confusion. I think they should be named ::PtrToConstMsg and ::PtrToMsg, respectively. This is so much more clear and easy to understand. I recommend that ROS make that change.

edit flag offensive delete link more

Comments

So if at some point I need to create a copy of the message that is a ConstPtr& msg, would I need to do **msg?

adi gravatar image adi  ( 2020-10-26 11:22:47 -0600 )edit
1

@adi, no, a const ConstPtr& msg is NOT a pointer to a pointer to a message, it is a reference to a smart pointer to a message. You treat references the same as if they were the object itself. Do some reading up on references in C++. So, you'd only need to dereference the one smart pointer (shared_ptr) with a single asterisk (*), like this: *msg.

eRCaGuy gravatar image eRCaGuy  ( 2020-10-29 12:21:30 -0600 )edit

In someone's code I've seen:

void odomCallback(const nav_msgs::Odometry::ConstPtr &msg)

Does it matter if the & is in front of msg instead of at the end of ConstPtr? How is this different? Is the message being passed as a reference instead of the pointer? What does that imply?

jorgemia gravatar image jorgemia  ( 2020-12-03 13:38:10 -0600 )edit

@jorgemia, it makes no difference. const type& msg and const type &msg are the same thing--personal style preference. This is a generic C++ question, so feel free to search around the internet, but where you put the space around reference (&) and pointer (*) symbols doesn't matter. Just choose one you like and stick with it, or do whatever the code you are working in does. Also, go do some reading on references and pointers in C++. To pass a raw pointer, you might define a function: void myfunc(sometype * ptr), and you call it with myfunc(&variable). To pass a reference, you might define a function: void myfunc(sometype& ref), and you call it with myfunc(variable). In a definition, & means "reference", but outside of a definition, it means "address of". In a definition, * means "pointer to" (which is an address), but outside a definition, it means "contents ...(more)

eRCaGuy gravatar image eRCaGuy  ( 2020-12-03 13:47:27 -0600 )edit

@jorgemina, here are 3 things you need to go spend 1 to 5 whole days or so studying: 1) C/C++ pointers (sometimes called "raw pointers" in C++, so as to distinguish them from smart pointer objects), 2) C++ references, 3) C++ smart pointers, which are actually class objects which manage raw pointer memory and act like raw pointers.

eRCaGuy gravatar image eRCaGuy  ( 2020-12-03 13:57:24 -0600 )edit

Thanks for the detailed answer! Very useful! Yes, I just spent the last hour learning about pointers and references but hadn't seen the position of the & or * being mentioned anywhere, all the examples had it next to the type. Going to continue reading now! 🤓

jorgemia gravatar image jorgemia  ( 2020-12-03 14:36:52 -0600 )edit

I wrote this short program to try and understand how it all works:

// Example program
#include <iostream>

struct odomData {
  int x = 3;
  int theta = 2;
};

void GetData( odomData*& msg ) //Passing the pointer by reference, so use the &
{
  int speed = msg->x; //Accessing the data in the struct
  int yaw = (*msg).theta; //Another way of accessing the data that has been passed
  // print
  std::cout << speed << std::endl;
  std::cout << yaw << std::endl;
}

int main( void )
{

  odomData d;
  odomData* ptr = &d; //The pointer (of type odomData*) holds the address of the struct d of type odomData

  GetData( ptr ); // Call the function to get the data, passing the pointer by reference

  return 0;
}

I believe that should be correct. In ROS we simply use ::ConstPtr to define the message type instead of explicitly using the "*" to make it a smart pointer?

jorgemia gravatar image jorgemia  ( 2020-12-04 06:50:58 -0600 )edit

Therefore, ::ConstPtr& can be understood and read as "reference to a shared pointer to a constant message", and ::Ptr& can be understood and read as "reference to a shared pointer to a (modifiable) message".

Why are we assuming that the msg variable used in the original question will always take the same value?

skpro19 gravatar image skpro19  ( 2020-12-20 02:50:44 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

3 followers

Stats

Asked: 2015-07-03 14:02:45 -0600

Seen: 24,558 times

Last updated: Jun 10 '20