3

While I know it's not necessarily the best way to code, I would like to initialize a pointer inside of a function. Then, I can use it later and delete it. It should look something like this:

#include <iostream>

void initializer(double *d_ptr)
{
    d_ptr = new double;
}

int main(int argc, char **argv)
{
    double *my_d;

    initializer(my_d);
    *my_d = 2;
    std::cout << *my_d << std::endl;

    delete my_d;
}

However, this results in segfaults. Why?

Joel
  • 1,868
  • 1
  • 17
  • 29
  • @LogicStuff I know the fundamental error is how to pass a pointer by reference (not understanding how to pass a pointer by reference) but these answers are impossible to find when searching for how to initialize a pointer inside of a function. I think the fundamental error is a duplicate, but this question is not a duplicate because the similar answers already indicate you know what you're doing. This question is about how to figure out why the function is not initializing properly, even though it compiles. – Joel May 03 '16 at 20:06
  • @juanchopanza see above? – Joel May 03 '16 at 20:06
  • Actually... I just read stackoverflow's use of duplicates. It looks like this falls into the case where it is a duplicate, but the question shouldn't be deleted because the question is unique and it's hard to find the linked answers if you have this problem. Does that sound right? http://stackoverflow.com/help/duplicates – Joel May 03 '16 at 20:10

1 Answers1

4

The problem lies in the function. It receives double *d_ptr. This means that d_ptr is a pointer to a double. But when you do:

d_ptr = new double;

this reassigns the pointer d_ptr a new address, without affecting the external pointer passed to the function.

What we want to do is assign the external pointer a new address. This means that when we do d_ptr = new double; we want d_ptr to be a reference to the external pointer. Then, by assigning d_ptr a new address, we assign the external pointer a new address. The correct way for the function to receive a pointer is:

void initializer(double *&d_ptr)

This means that the function has a variable d_ptr that is a reference to a pointer of type double. One character fixes everything:

#include <iostream>

void initializer(double *&d_ptr)
{
    d_ptr = new double;
}

int main(int argc, char **argv)
{
    double *my_d;

    initializer(my_d);
    *my_d = 2;
    std::cout << *my_d << std::endl;

    delete my_d;
}
Joel
  • 1,868
  • 1
  • 17
  • 29
  • This is a lot of explaining for something simple. Your explanation is no different than if you tried to change the value of any parameter passed to a function, and have the change reflect back to the caller. You pass a reference to that type, and in this case, the type is a pointer, so you pass a reference to the pointer. – PaulMcKenzie May 03 '16 at 20:23
  • [Simple example using `int`:](http://ideone.com/zAmV4d) – PaulMcKenzie May 03 '16 at 20:29
  • It's simple in hindsight, I agree; just not in foresight. It took me a while to think in terms of pointers having values which are addresses. I thought by passing a pointer it would get copied onto the new pointer, which I could use in place of the original. That's not how it works, and it was definitely not obvious to me that I needed a reference to a pointer and how to code that. – Joel May 03 '16 at 20:29
  • Well, think of it this way -- an `int` is a type, and an `int *` is a totally different type, even though you see the word `int` there. So given that, the rules stay the same -- you want to change an `int*`, you pass a reference to it, same as if you want to change an `int`. – PaulMcKenzie May 03 '16 at 20:31
  • @PaulMcKenzie As a C++ convert, I don't tend to think of pointers as a datatype. I think about them as a deeper sort of magic that allows you to interact with the addresses of things, and not just the things. I haven't internalized it to the point where I just see `*` as an operator, or `int *` as a type. I have to think what that really means. – Joel May 03 '16 at 20:33
  • Nope, it's a different type. For example, what does `sizeof(char)` return to you, as opposed to `sizeof(char*)`? The `sizeof()` operator takes the type and returns the size, in bytes. The types happen to be `char` for the first one, and `char*` for the second. – PaulMcKenzie May 03 '16 at 20:35
  • @PaulMcKenzie Dude, I don't know why you feel the need to correct me on this. I figured it out. What issue is there left? Did I say something incorrect in my answer? Or do you just not like that some people don't have a perfect understanding of pointers and need some help? – Joel May 03 '16 at 20:38
  • What I'm saying is that it is not a different set of rules because a pointer needs to be changed within a function. That IMO is the easiest explanation. If they see the simple example of why it doesn't work for one type (as I showed), then it becomes easier to see why it doesn't work for another type. – PaulMcKenzie May 03 '16 at 20:42
  • @PaulMcKenzie Disagree. I understand ints. I don't understand pointers. Ints don't have an "int dereference operator". I haven't had any problem messing around with using references to various classes and datatypes. I did have a problem with pointers. In hindsight, and if you're a teaching a class- great. But approaching the problem, that's not how my brain works. – Joel May 03 '16 at 20:44
  • An int doesn't have destructors or constructors, don't have virtual functions, etc. yet the same rule applies to classes and structs that have these properties. – PaulMcKenzie May 03 '16 at 20:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110939/discussion-between-joel-and-paulmckenzie). – Joel May 03 '16 at 20:46