a = b = new c?

Started by
36 comments, last by Paradigm Shifter 10 years, 9 months ago

So the conclusion is that the value of b is assigned to a?

OK, I am saying this poorly.

take

a = b = new c();

You change the value of b and a changes too, as a points to b, not c.

That is what I meant to say all along.

So, say using less abstract variables:

monster1 = monster2 = new Orc();

monster2 = new Gorgon();

At this point, people might think monster1 is still pointing at an Orc, it isn't, it's pointing at a Gorgon.

People would be correct. You are incorrect. monster1 is still pointing at the new Orc.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
Advertisement

So the conclusion is that the value of b is assigned to a?

*initially*

What happens after "initially"?

I edited.

All right, let's ask the compiler again.


int main()
{
    int *a, *b;

    a = b = new int;

    std::cout << "value of a is " << a << std::endl;
    std::cout << "value of b is " << b << std::endl;
    std::cout << "address of b is " << &b << std::endl;

    b = new int;

    std::cout << "value of a is " << a << std::endl;
    std::cout << "value of b is " << b << std::endl;
    std::cout << "address of b is " << &b << std::endl;
}

a = b = new c creates (allocates) one object of type c, then assigns the pointer to b, and then assigns the same pointer to a.

Careful, that isn't actually true.

a will point to b, while b will point to c. The fact that b currently points to c wont hold true if b is reassigned.

... I think I said that poorly.

http://objection.mrdictionary.net/go.php?n=6774974

Actually that captures it perfectly ( and is completely wrong! ;) ).

The address of b is assigned to a, not the value. This is exactly what I was warning of.

No. First, a = b = new c is -- regardless of types or whether they're values or pointers --- equivalent to a = (b = new c). It means assign return value of "create c", to b, then assign b to a, not something different, ever. That's how the language is defined.

new c returns a pointer to the newly created object of type c (or throws), which necessarily means that b must be of type c* (pointer-to-c) or at least a compatible pointer (e.g. base class of c), or well, a compatible smart pointer. Otherwise this will not compile.

This, by consequence, means that a also has to be of type c*, because you cannot assign a pointer to "something else", say, an integer, or an object (not without a cast, a conversion operator, or a compile error, anyway), and a therefore also points to c (which is the value [of pointer-type] of b).

a does not point to b. It is assigned b's value (not its address!), which is a pointer to c.

Yes, you could of course be extra smart and define a as a class that has a constructor taking a pointer to type c, but that's a sophistry. It is technically possible to abuse the language in a way which makes this possible, but meh.

No, we are saying the same thing I am just doing a poor job of it.

a = b = new c()

The b points at the newly allocated memory address, while a points at b, so they effectively have the same value. It does not create two new memory allocations like a new developer might expect, it creates one and points b at that address, then points a at b which ultimately points a c. If you change b to point at something else, a will point at something else as well, because a is pointing at the address of b, not the original value c like some might expect. The above line of code creates a single memory allocation. If you change what b points at, you change was a points at, as a points at b, not c. This is where I think a new developer will get hung up.

So,


int sample = 42;
int sample2 = 43;
int *a;
int *b;
a = b = &sample;

cout << a;  // 42
b = &sample2;
cout << a; //43;

That's completely wrong...

cout << a; // prints the address of a

b = &sample2; // does not affect the value of a at all, it is still pointing to sample, i.e. a holds &sample.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Your code prints the following for me (with a line break added):

000000000019FBB4
000000000019FBB4

Clearly the value of a has not changed after assigning b a new value.

That's completely wrong...

cout << a; // prints the address of a

b = &sample2; // does not affect the value of a at all, it is still pointing to sample, i.e. a holds &sample.

Ug, you are right, absolute brain fart on my behalf.

Furthermore printing out *a instead of a will reveal that *a is 42 on both occasions as well. I dunno if Serapth is having a brain-fart or if his account has been hacked by someone not deserving his high rating??

EDIT: Brain fart it was ;)

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Furthermore printing out *a instead of a will reveal that *a is 42 on both occasions as well. I dunno if Serapth is having a brain-fart or if his account has been hacked by someone not deserving his high rating??

EDIT: Brain fart it was ;)

In my defense, it is Canada Day, I am Canadian and over the age of 19...

In other words, I think im going to stop posting in technical threads until the celebrations are over. :) My apologies for confusion.

OK, carry on listening to Celine Dion, Rush and Bryan Adams ;)

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

OK, carry on listening to Celine Dion, Rush and Bryan Adams ;)

Celine Dion is a resident of Vegas now, thank god. :)

Well to prevent any confusion this is what really happens in Serapth's example (with some corrections, i.e. using *a rather than a)


int sample = 42;
int sample2 = 43;
int *a;
int *b;
a = b = &sample;

cout << *a;  // 42
b = &sample2; // this does NOT change a, nor *a
cout << *a; // 42
cout << *b; // 43

Output:

424243

(maybe should add some endl's in there too ;) )

EDIT: Other example


#include <iostream>

using namespace std;

class Monster
{
public:
    virtual void WhatAmI() { cout << "I'm a Monster" << endl; }
};

class Orc : public Monster
{
public:
    virtual void WhatAmI() { cout << "I'm an Orc" << endl; }
};

class Gorgon : public Monster
{
public:
    virtual void WhatAmI() { cout << "I'm a Gorgon" << endl; }
};

int main(void)
{
    Monster* monster1;
    Monster* monster2;

    monster1 = monster2 = new Orc;

    monster1->WhatAmI(); // "I'm an Orc"
    monster2->WhatAmI(); // "I'm an Orc"

    monster2 = new Gorgon;

    monster1->WhatAmI(); // "I'm an Orc"
    monster2->WhatAmI(); // "I'm a Gorgon"

    delete monster1;
    delete monster2; // if I didn't do monster2 = new Gorgon, this would be a double delete and an error

    return 0;
}
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

This topic is closed to new replies.

Advertisement