-2

Can we change the value of *y in void function(const int*& x ) when y (i.e int*y= new int) is passed as an argument to function()?

If anyone could put it in words it would be great. Please refer to the following code for a better comprehension of my question:

void DoWork(const int* &n)
{
    *n = *n * 2; // will this change the value of *a? 
}

int main()
{
    int* a= new int;
    DoWork(a);
}

I was trying to understand a program where I came across a similar syntax. Have a look at a snippet from that program:

void segmentTable(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud,
                  const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& seg_cloud){
  double z_min = -5, z_max = 0;
  
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  // Create the segmentation object
  pcl::SACSegmentation<pcl::PointXYZRGB> seg;
  // Optional
  seg.setOptimizeCoefficients (true);
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setDistanceThreshold (0.01);

  seg.setInputCloud (cloud);
  seg.segment (*inliers, *coefficients);
  // Project the model inliers
  pcl::ProjectInliers<pcl::PointXYZRGB> proj;
  proj.setModelType (pcl::SACMODEL_PLANE);
  // proj.setIndices (inliers);
  proj.setInputCloud (cloud);
  proj.setModelCoefficients (coefficients);
  proj.filter (*seg_cloud);
  /* Create Convex Hull to segment everything above plane */
  pcl::ConvexHull<pcl::PointXYZRGB> cHull;
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZRGB>);
  pcl::PointIndices::Ptr hull_inliers (new pcl::PointIndices);
  cHull.setInputCloud(seg_cloud);
  cHull.reconstruct(*cloud_hull);
  cHull.setDimension (2);
  if (cHull.getDimension () == 2){
    pcl::ExtractPolygonalPrismData<pcl::PointXYZRGB> prism;
    prism.setInputCloud (cloud);
    prism.setInputPlanarHull (cloud_hull);
    prism.setHeightLimits (z_min, z_max);
    prism.setHeightLimits (z_min, z_max);
    prism.segment (*hull_inliers);
  }
  pcl::ExtractIndices<pcl::PointXYZRGB> extract_indices;
  extract_indices.setInputCloud(cloud);
  extract_indices.setIndices(hull_inliers);
  extract_indices.setNegative(true);
  extract_indices.filter(*cloud);
}



void int main(){pcl::PointCloud<pcl::PointXYZRGB>::Ptr temp_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
  pcl::fromPCLPointCloud2(pcl_pc2,*temp_cloud);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr seg_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
  
  passThroughFilter(temp_cloud);
  
  segmentTable(temp_cloud, seg_cloud);}

This code does change the values in temp_cloud and seg_cloud.

  • The declaration `const int* &n` says that "`n` is a reference to a pointer to an `int` which is constant". It is the value that `n` is pointing to that is constant, therefore the assignment is invalid. Which [the compiler should have told you](https://godbolt.org/z/88d9eM15j). – Some programmer dude Dec 05 '21 at 08:50
  • Also note that unless you want to modify the pointer itself (where `n` is pointing) there's almost never a use to pass pointers by reference. – Some programmer dude Dec 05 '21 at 08:52
  • I think pretty much of how const works in such case is already in depth explained here: https://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const?rq=1 – πάντα ῥεῖ Dec 05 '21 at 08:52
  • @Someprogrammerdude I can show you a code where it is possible to change the values of *a in such cases. – Shivam Siuu Dec 05 '21 at 08:55
  • @ShivamSiuu If you have a problem with your other code, please post it as a separate question! The details of `const` are quite tricky; it's possible that the answer to the other question would be something entirely different. – anatolyg Dec 05 '21 at 08:57
  • You could introduce a type alias which could perhaps clarify `const int*&` a bit: `using ValueType = const int; using ValuePointer = ValueType*;` which allows you to write `ValueType*&` or `ValuePointer&` instead of `const int*`, i.e. you've got a reference to a pointer that allows you to modify the value of the pointer: `delete n; n = new int;`, you cannot modify the value the pointer points to directly though, e.g. `*n = 2` results in a compiler error. – fabian Dec 05 '21 at 08:57
  • The big code blob you added doesn't contain any references to pointers. – Ted Lyngmo Dec 05 '21 at 09:06
  • @Ted Lyngmo In ''const pcl::PointCloud::Ptr& cloud'' Ptr means pointer – Shivam Siuu Dec 05 '21 at 09:06
  • Oh, a pointer in disguise. Well, I don't think that code helps to clarify the question. It was pretty clear without it. – Ted Lyngmo Dec 05 '21 at 09:07
  • @TedLyngmo this code does change the values of *temp_cloud, *seg_cloud. I don't know why. This code works – Shivam Siuu Dec 05 '21 at 09:10
  • The two pieces of code you posted are not equivalent. I hope you can understand why from [this answer](https://stackoverflow.com/a/1143344/509868) to the linked question. If not, maybe someone cares enough to explain this in a proper answer. – anatolyg Dec 05 '21 at 09:13
  • The added code is invalid. Most compilers will refuse `void int main()` – Ted Lyngmo Dec 05 '21 at 09:13
  • @TedLyngmo I can upload it on Github or show you the screenshot of it compiling successfully. – Shivam Siuu Dec 05 '21 at 09:17
  • @ShivamSiuu Please read my updated answer – Ted Lyngmo Dec 05 '21 at 09:18
  • @anatolyg that link does make sense, but the big blob of code I attached with my question works doesn't make sense. – Shivam Siuu Dec 05 '21 at 09:19
  • @ShivamSiuu Did you read my updated answer? The types in your example and in the added code are not the same – Ted Lyngmo Dec 05 '21 at 09:21
  • 1
    You have a memory leak in your code. `a` is never deleted. Don't use raw pointers in C++. use `std::unique_ptr`. – JHBonarius Dec 05 '21 at 09:23

1 Answers1

2

No, you are not allowed to change *n since it's a const int. You need to make it non-const for it to work:

void DoWork(int*& n)
{
    *n = *n * 2;
}

Also note that *a is uninitialized so reading it would make the program have undefined behavior. You need to initialize it:

int main()
{
    int* a = new int{1};   // *a is now initialized to 1
    DoWork(a);
    delete a;              // and delete
}

The global int a; that you added isn't involved here. The local a in main shadows the global a in main and it's that local a that is passed as an argument to DoWork.

The code in the added block doesn't do the same thing. In your added code block the value Ptr is pointing at is non-const so there the value can be changed. Consider this:

using Ptr = int*;

void foo(const Ptr& p) {     // p = int* const&
    *p *= 2;                 // ok, *p is an int, not a const int
    // p = nullptr;          // error, the pointer is const
}

int main() {
    int* a = new int{1};
    foo(a);
    delete a;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Although complete, I don't think we should be teaching modern C++ using raw pointers. It's not C and we have RAII. – JHBonarius Dec 05 '21 at 09:21
  • @JHBonarius Indeed, but it'll be trickier to answer in an understandable way without using the same types as OP used. – Ted Lyngmo Dec 05 '21 at 09:23
  • This was literally my answer @TedLyngmo This last code block is correct, right? I answered the same thing! It would also change the value of *a, right? – Shivam Siuu Dec 05 '21 at 09:28
  • @TedLyngmo does space between Ptr, & and p matter? – Shivam Siuu Dec 05 '21 at 09:32
  • @ShivamSiuu I wasn't able to understand your answer when you only had the first code snippet in your question. I kind of understand what you mean now but it refers to `DoWork` in "_Therefore, we can change the value of *a inside DoWork()_" which doesn't make sense. You would have to show the type definition for `Ptr` and use that in `DoWork` for your answer to be understandable. No, the space doesn't matter. I just prefer to separate the identifier from the type – Ted Lyngmo Dec 05 '21 at 09:33
  • @TedLyngmo can you please add in your answer that your last code block works and it does change the values to which "a" pointer points? I will accept it after that. The conclusion of your answer might be unclear to someone else. – Shivam Siuu Dec 05 '21 at 09:40
  • 1
    @ShivamSiuu I was hoping that _`// ok, *p is an int, not a const int`_ would make make that clear. but I added a more verbose text above. – Ted Lyngmo Dec 05 '21 at 09:42