1

I learned that in Java and C, you can assign a pointer, pass the pointer to a method, follow the pointer in the method and change the data that was pointed to. However, you cannot change where that pointer points.

I thought I could see a different behavior in C++ due to its pass-by-reference feature, but my code seems to agree with the above statement...

void reassign(string & a);
int main()
{
    string x = "abcd";
    cout <<"x is " << x <<" at " << &x <<endl;    //"x is abcd at 0x7bc7ebd5b720"
    reassign(x);
    cout <<"x is " << x <<" at " << &x <<endl;    //"x is efgh at 0x7bc7ebd5b720"

}

void reassign(string & a)
{
    a = string("efgh");
}

Since "string()" constructs a new string, why doesn't the "reassign" function change the original string's address?

Community
  • 1
  • 1
ladiesman
  • 39
  • 6
  • Why would you think that constructing a new object into a reference implies relocating the referenced object? – Daniel Kamil Kozar May 20 '15 at 19:17
  • `reassign()` is simply constructing a new string in the same memory location that `a` is referencing. If you wanted to change the address, you would need to pass a either a reference to a pointer, or a pointer to a pointer. – Austin Brunkhorst May 20 '15 at 19:21
  • You are not actually printing where the pointer points. You are just printing the address of a pointer to where x is. – RealSkeptic May 20 '15 at 19:22
  • 1
    When you pass an object by reference, the function can change the value of the object using that reference. But it can't "reseat" the reference to make it refer to a different object entirely. – David Schwartz May 20 '15 at 19:25
  • Java's "references" and C++'s "references" are different things. Imagine a stationary box where you can put things. A Java "reference" would refer to the thing inside the box, while a C++ "reference" would refer to the box itself. Put another way: in Java, a "reference" always refers to the same thing, regardless of which box you put it in; in C++, a "reference" always refers to the same box, regardless of what you put into it. – molbdnilo May 20 '15 at 19:46
  • so isn't `"string mystr = string("newstring")"` the same as `"string mystr = *(new string("newstring"))"` in terms of dynamically memory allocation? – ladiesman May 20 '15 at 20:31

2 Answers2

6

Once an object is allocated, nothing can change its address. You can change its content (that is what your program does) but the address will stay the same for the lifetime of the object.

If you create an object dynamically with new, you would be able to assign a different object to the same pointer. However, the rule would stay the same: the address of the old object would not change, but you would be able to assign a new object to an old pointer.

void reassign(string* & a);

int main() {
    string *x = new string("abcd");
    cout <<"x is " << *x <<" at " << x <<endl;    //"x is abcd at 0x95b7008"
    reassign(x);
    cout <<"x is " << *x <<" at " << x <<endl;    //"x is efgh at 0x95b7030"
    delete x;
    return 0;
}

void reassign(string* & a) {
    string *old = a;
    a = new string("efgh");
    delete old;
}

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • If you delete the object before reassigning, you may reuse the same address, breaking the demo. That's why I saved `a` to `old`, reassigned `a`, and only then deleted `old`. – Sergey Kalinichenko May 20 '15 at 19:28
0

You are confused because your analogy is not right. In Java, there is no such thing as an "argument object", because "objects" themselves are not values in Java (there are no "object types" in Java). The only types in Java are primitive types and reference types, where "references" are pointers to objects. So in Java you can only have pointers to objects as the value of a variable or parameter, and you only deal with objects through pointers to objects.

"you cannot change where that pointer points" is a consequence of pass-by-value. Java is always pass-by-value, which means assignment to the parameter cannot change the value of a passed variable. Remember that variables can only be of primitive type or reference type. Here you are talking about reference type. So the "value" of a variable of reference type is the reference (pointer to object), i.e. the address of the object it points to. Hence, you cannot change the value means you cannot change where the pointer points.

For example, in Java you might have something like this:

public static void reassign(String a) {
    a = new String("efgh");
}

public static void main(String[] args) {
    String x = "abcd";
    System.out.printf("x is %s at %x\n", x, System.identityHashCode(x)); // x is abcd at 25154f
    reassign(x);
    System.out.printf("x is %s at %x\n", x, System.identityHashCode(x)); // x is abcd at 25154f
}

Here, x in main is a pointer to an object. a in reassign is also a pointer to an object. Assigning to the pointer parameter a in reassign has no effect on the passed pointer variable x (i.e. it does not affect where the pointer points to) because it's pass-by-value.

The equivalent of the above code in C++ would be like this:

void reassign(string *a) {
    a = new string("efgh");
}

int main() {
    string *x = new string("abcd");
    cout << "x is " << *x <<" at " << x << endl; // x is abcd at 0x82b1008
    reassign(x);
    cout << "x is " << *x <<" at " << x << endl; // x is abcd at 0x82b1008
    return 0;
}

In addition to the pass-by-value shown above, C++ also has pass-by-reference, where assignment to a parameter has the same effect as assigning to the passed variable in the calling scope. Here is the exact same thing as above but with pass-by-reference:

void reassign(string *&a) {
    a = new string("efgh");
}

int main() {
    string *x = new string("abcd");
    cout << "x is " << *x <<" at " << x << endl; // x is abcd at 0x8673008
    reassign(x);
    cout << "x is " << *x <<" at " << x << endl; // x is efgh at 0x8673030
    return 0;
}

Note that in none of the cases here did we change the object pointed to. We simply created a new object and tried to change the pointer to point to this object. The old object is still unchanged. The ability to change an object is an independent and orthogonal issue from pass-by-value and pass-by-reference, so we do not go into it here.

newacct
  • 119,665
  • 29
  • 163
  • 224