0

given the following snippet

class Box {
public:
    int name;
    int length;
};


std::ostream &operator<<(std::ostream &os, Box &box) {
    os << "Box name: " << box.name << " and length: " << box.length;
    return os;
}

int main() {
    Box box1;
    box1.name = 1;
    Box box2;
    box2 = box1;
    box1.name = 2;

    std::cout << box1 << std::endl;
    std::cout << &box1 << std::endl;
    std::cout << box2 << std::endl;
    std::cout << &box2 << std::endl;


    return 0;
}

could someone explain me why it prints the following results?

Box name: 2 and length: 4201248
0x61ff08
Box name: 1 and length: 4201248
0x61ff00

I expected to have the name of box2 equals to 2, since box1 and box2 should be pointing to the same object.

  • It is a foundational feature of C++ (as C) that it has value semantics by default, so they don't point to the same object at all. You copied the object, not create another reference to it. – underscore_d Dec 03 '20 at 14:57
  • Does this answer your question? [What are the differences between a pointer variable and a reference variable in C++?](https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in) – Jean-Benoit Harvey Dec 03 '20 at 15:12
  • I think this question is more like default assignment operator in C++, and of course pointers and references – Alberto Tiraboschi Dec 03 '20 at 15:19

2 Answers2

2

box1 and box2 are their own objects. They can never refer to any object except themselves.

Assignment in C++ is done by value. When you assign box2 = box1; you copy the current, immediate value (the state) of box1 to box2. It does not create a relationship between the two.

You may be relying on your experience with other languages, like Java, where assignment usually changes which object an identifier refers to. This is different from how assignment works in C++.

If you want objects that can refer to some other instance, you can use a pointer or a reference. Here is your example modified to use a pointer such that changes to an object are visible through the pointer.

#include <iostream>

class Box {
public:
    int name;
    int length;
};


std::ostream &operator<<(std::ostream &os, Box &box) {
    os << "Box name: " << box.name << " and length: " << box.length;
    return os;
}

int main() {
    Box box1;
    box1.name = 1;

    // Use a pointer instead
    Box * box_ptr = &box1;

    // This change is visible through *box_ptr
    box1.name = 2;

    std::cout << box1 << std::endl;
    std::cout << &box1 << std::endl;
    std::cout << *box_ptr << std::endl;
    std::cout << box_ptr << std::endl;


    return 0;
}

The value of a pointer is which object it refers to. So assignment for a pointer will change which object it refers to, like you expected.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
  • So box2 = box1 means: box2.name = box1.name; box2.length = box1.length ? – Alberto Tiraboschi Dec 03 '20 at 15:02
  • 2
    @AlbertoTiraboschi Because `Box` is a `class` type, the assignment is handled by the `Box::operator=` assignment operator. Since you did not provide one, a default operator is generated for you. By default, the assignment operator performs assignment on each member. So for `Box` the expression `box2 = box1;` is equivalent to `box2.name = box1.name; box2.length = box1.length;`. It will assign every member by copy. – François Andrieux Dec 03 '20 at 15:05
  • So if an attribute of Box were an object I suppose it would recursively go in the same way, right? – Alberto Tiraboschi Dec 03 '20 at 15:06
  • @AlbertoTiraboschi Yes, it would apply recursively. Edit : you can try this by replacing `int name;` with `std::string name;`. You will see that the `name` is copied, even though it is a `class` type. – François Andrieux Dec 03 '20 at 15:07
0

since box1 and box2 should be pointing to the same object.

Your expectation is unreasonable. box1 and box2 aren't pointers, so they don't point to anything.

You have two objects named by two variables. When you assign an object (with implicitly generated assignment operator), you copy the members of the right operand to the members of the left operand. The behaviour of the example program is undefined because you read an uninitialised member (length) from the right operand (and again later when inserting to the output stream).

You could achieve what you wanted by defining a reference variable:

Box& box2 = box1;
eerorika
  • 232,697
  • 12
  • 197
  • 326