0

Ok, here i have 2 simple C++ examples, the first one is:

MyClass

class MyClass

{
private:

    int test;

public:

        int member(){ 
            test = 456;
            return 1;
        } // one public function

};

global function definition

int funct(MyClass** obj)
{
    *obj = new MyClass();
    int c = (**obj).member();
    return 1;
}

main

...

MyClass* object;
int i = funct(&object);
...

while in the second case, i modify the main like this:

MyClass** object = (MyClass **)malloc(sizeof(MyClass));
int i = fun(object);

Both examples work fine, but i'm not sure if i understood correctly why ONLY in this second case i need a malloc (otherwise it wouldn't compile at all).

Thanks in advance for your help

PS: i know double pointers are more C-style programming, but i'm currently experimenting with both languages.

rekotc
  • 595
  • 1
  • 10
  • 21

3 Answers3

1
MyClass** object = (MyClass **)malloc(sizeof(MyClass));

actually this is wrong, malloc will return pointer to allocated memory: MyClass *, so if you later do: *object and would like to see a pointer to MyClass you will be wrong. You should rather:

MyClass* pobject = (MyClass *)malloc(sizeof(MyClass));
MyClass** ppobject = &pobject ;

your question is unclear to me - sorry,also it is not wise to allocate clases with malloc - your one looks like its POD - so it seems to be safe, but I would check it with std::is_pod.

[edit]

working example is below. You asked why you need initialization of object in the second case, thats because in first case you reserve storage for your pointer by simply defining pointer variable : MyClass* object;. Here object can be safely used in funct. In second example, you dont have reserved memory (in this case space on stack) for your pointer to MyClass, so you must allocate it with malloc or new. Hopefully thats clear enough.

MyClass** object = (MyClass **)malloc(sizeof(MyClass*));
//MyClass** object = new MyClass*;

int i = funct(object);

delete *object;
free(object);
//delete object;
marcinj
  • 48,511
  • 9
  • 79
  • 100
  • sorry if it seems unclear, i tried to clarify in another comment in this page, i thought it was enough to just write "MyClass** object;" without any actual allocation until funct() gets executed. The same as in the first example. But the compiler complains with error C4700. – rekotc Jun 02 '15 at 15:08
  • his code is weird, so for equivalence with his example 1 he'd need to allocate MyClass** = (MyClass**)malloc(sizeof(MyClass*)); – No-Bugs Hare Jun 02 '15 at 15:09
0

First of all, you have a bug (and the whole thing works only because sizeof(MyClass)>=sizeof(MyClass*)):

MyClass** object = (MyClass **)malloc(sizeof(MyClass));

is incorrect, should be

MyClass** object = (MyClass **)malloc(sizeof(MyClass*));

or

MyClass** object = new MyClass*;

Second, you do need malloc() (or new) because you need your double pointer MyClass** to point to some instance of MyClass*. Your first and second (after correction) example differ only in a way where you get this MyClass* - in first example it is on-stack, in second example it is on heap.

Oh, and when it on heap, you need to manually call free() (if malloc() was used to allocate it) or delete (if new was used) for the pointer.

No-Bugs Hare
  • 1,557
  • 14
  • 15
  • ok, i almost got it, thank you. In the second case my code "worked" only because the class MyClass contains just an int, right? What i still don't get is why the compiler needs my double pointer to point to something, while the single pointer can stay unallocated until i call the funct() – rekotc Jun 02 '15 at 15:17
  • In the second case, your code "worked" because you provided enough space to place at least one pointer. Why compiler needs your double pointer to point somewhere - it doesn't, but you will be writing to the point where it points (as soon as you pass the double-pointer to funct()) - and when you're writing to a memory pointed to by uninitialized pointer - you're in trouble. – No-Bugs Hare Jun 02 '15 at 15:26
  • thank you again for your patience... but i really don't get this part: in the first example i pass the single pointer to funct() without any initialization, and the compiler doesn't say anything, what's different in the second case? – rekotc Jun 02 '15 at 15:30
  • i'm about the code i post here, the first example works fine and there is not initialization for MyClass* object in the main, while in the second case i MUST initialize MyClass** object in one of the ways you suggested, otherwise the compilers gives a C4700 error "uninitialized variable 'object' used" – rekotc Jun 02 '15 at 15:38
  • Just tried it without initializing MyClass** object: it complies for me, but (expectedly) core dumps. – No-Bugs Hare Jun 02 '15 at 15:55
0

I deleted my previous answer. This is how you should go about initializing the double pointer:

MyClass** object;
object = new MyClass*;
int i = funct(object);

The second line allocates a new pointer to an instance of MyClass, and the call to funct allocates an actual object of MyClass. After this call, object will point to a valid pointer to a valid instance of MyClass.

Carlton
  • 4,217
  • 2
  • 24
  • 40
  • ok, thank you very much :) I still dont get why i don't need to initialize anything if i use a single pointer, but i must initialize the double pointer. – rekotc Jun 02 '15 at 15:23
  • In the first case, you declare a pointer to a `MyClass`. Even though this pointer is just pointing to garbage, it is still a valid object so you can take its address and pass by-reference when you call `funct`. In the second case, you declare a pointer to a pointer. The pointer itself is a valid object, but it does not yet point to a valid pointer. That's the reason you have to call `new MyClass*` - to make `object` point to a valid pointer. – Carlton Jun 02 '15 at 15:39
  • ok, so, if i got it right, a single pointer is initialized automatically (to garbage), while a double pointer is not. Right? That's why i need to manually initialize it to something meaningful, and that's why the compiler complains if i don't. – rekotc Jun 02 '15 at 15:50
  • Unless you initialize it explicitly, every pointer points to garbage, by which I mean it points to a random memory address. So, in both your cases, you declare uninitialized pointers. The only difference is the *type* of garbage they point to; in the first case, `object` points to an uninitialized `MyClass` while in the second case it points to an uninitialized `MyClass*`. I *always*, *always* initialize pointers to `nullptr` like this: `MyClass* object = nullptr;` because I have gotten burned so many times by forgetting to allocate a valid object to the pointer. – Carlton Jun 02 '15 at 16:02
  • ok, forgive me for this last question, i really want to get to the bottom of it. Why, if both pointers point to something uninitialized, the first example can be run without problem, and the second necessarily needs an initialization of some kind? does it all boil down to the fact that the first pointer points to an object and the second one points to a pointer to an object? I know it looks like i'm losing my mind on nothing, but... i can't stop thinking about this difference. – rekotc Jun 02 '15 at 17:47
  • Yes, you basically have it. The pointer in the first example is valid, but points to nothing useful until you pass it to `funct` where it is assigned to point to a valid `MyClass`. In the second example, the pointer-to-pointer you named `object` also points to nothing useful, until you assign to it with `object = new MyClass*;`. After that line, `object` points to a valid pointer. BUT, the pointer created with `new` does not yet point to anything useful, until you pass it to `funct`. After that call, `object` points to a valid pointer, which points to a valid instance of `MyClass`. – Carlton Jun 02 '15 at 17:59