HiroIshida
HiroIshida

Reputation: 1603

cannot access properly after getting pointer of a member of struct

In the following example, I basically tried to get the pointer of the element of the vector in the data. For me, those three methods seems to do the same thing, but the result is different :

123
9.88131e-324
5.61658e+259

and only via first method, the element is accessed properly. Could you point out my mistake and explain why these output's out these three method is different?

#include<vector>
#include<iostream>
using namespace std;

struct Data
{
  vector<double> a;
  Data() : a(vector<double>(100, 123.0)) {};
  double* get_ptr(int idx){
    return &a[idx];
  }
  void get_ptr2(int idx, double* ptr){
    ptr = &a[idx];
  }
};

int main(){
  auto data = Data();
  std::cout << *(data.get_ptr(10)) << std::endl; 

  double value;
  data.get_ptr2(10, &value);
  std::cout << value << std::endl; 

  double* ptr;
  data.get_ptr2(10, ptr);
  std::cout << *ptr << std::endl; 
}

Upvotes: 0

Views: 365

Answers (1)

David C. Rankin
David C. Rankin

Reputation: 84642

The primary problem you have in get_ptr2, e.g.:

  void get_ptr2(int idx, double* ptr){
    ptr = &a[idx];
  }

is that ptr will be a copy of the pointer from main(). When you change the value of ptr in your function, you are changing the value of the local copy of ptr and the results are never seen back in main().

(note the following shows you how to accomplish what you are attempting, but doesn't recommend it as the proper way to do it. See comment by @tadman below your original question)

You can pass the address of a pointer from main() and update the pointer at that address, e.g.

  void get_ptr2(int idx, double** ptr){
    *ptr = &a[idx];
  }

and called as:

  double* ptr;
  data.get_ptr2(10, &ptr);
  std::cout << *ptr << std::endl; 

Pointer will hold the correct address and dereferencing the pointer will provide the wanted value.

Your option with value is a bit different. There, you can pass a pointer reference, overloading a second get_ptr2(), e.g.

  void get_ptr2(int idx, double*& ptr){
    ptr = &a[idx];
  }

But, you cannot pass the address of value which is an rvalue as the reference. You can create a second pointer holding the address and update the value held by the pointer, e.g.

  double value, *valptr = &value;
  data.get_ptr2(10, valptr);
  std::cout << *valptr << std::endl; 

Which also outputs the desired value.

Example Code

The complete example would be:

#include<vector>
#include<iostream>
using namespace std;

struct Data
{
  vector<double> a;
  Data() : a(vector<double>(100, 123.0)) {};
  double* get_ptr(int idx){
    return &a[idx];
  }
  void get_ptr2(int idx, double*& ptr){
    ptr = &a[idx];
  }
  void get_ptr2(int idx, double** ptr){
    *ptr = &a[idx];
  }
};

int main(){
  auto data = Data();
  std::cout << *(data.get_ptr(10)) << std::endl; 

  double value, *valptr = &value;
  data.get_ptr2(10, valptr);
  std::cout << *valptr << std::endl; 

  double* ptr;
  data.get_ptr2(10, &ptr);
  std::cout << *ptr << std::endl; 
}

Example Use/Output

$ ./bin/get_ptr
123
123
123

Upvotes: 3

Related Questions