0
#include<iostream>
#include<string.h>
using namespace std;
class Student{
    int age;
    
    public:
    char *name;
    
    
    
    Student(int age,char *name){
        this->age = age;
        
        this->name = new char[strlen(name) + 1];
        strcpy(this->name,name);

    }
    void display(){
        cout<<this->age<<" "<<this->name<<endl;
    }
};

int main(){
    char name[] = "abcd";
    Student s1(20,name); 
    Student s2(s1);
    s2.name[0] = 'e';
    //s2.name = "abdd";
    cout<<&name<<endl;
    cout<<&s1.name<<endl;
    cout<<&s2.name<<endl;
    s1.display();
    s2.display();
}

OUTPUT :-

0x61ff0b
0x61ff04
0x61fefc
20 ebcd
20 ebcd

Why the addresses of s1.name and s2.name are different and still changes in s2.name is affecting s1.name??

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
Prathamt
  • 23
  • 3
  • 2
    Strongly recommended reading: https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three?r=Saves_AllUserSaves (if not a dupe) – πάντα ῥεῖ Aug 06 '23 at 07:33
  • 1
    Because you invoked the default bitwise copy constructor. Your class is also missing a destructor so it constitutes a resource leak, but if you define it you will need to write a proper copy constructor and assignment operator for it as well. Solution: use `std::string` instead of `char*`. – user207421 Aug 06 '23 at 07:36
  • 3
    *Why the addresses of s1.name and s2.name are different* -- Because they are different variables. One variable is a member of the `s1` instance, the other is a member of the `s2` instance. A pointer also has to live somewhere, and what you printed is where the pointers live, not what the pointers are pointing to. – PaulMcKenzie Aug 06 '23 at 07:39
  • Fyi, the address 'of' a pointer variable is rarely the same as the address 'held by' a pointer variable. – WhozCraig Aug 06 '23 at 07:41

2 Answers2

6

You're printing the address of the pointer variable rather than the value of the pointer itself.

We can simplify your example to:

char name1[] = "abcd";
char* name2 = name1;
std::cout << &name1 << "\n";
std::cout << &name2 << "\n";

This will print two different addresses of the two different variables but we still only have one array.

If you want to print the address of the array you need to cast to void* as the stream operator deliberately prints the contents of the null terminated string when passed a char*:

std::cout << static_cast<void*>(name1) << "\n";
std::cout << static_cast<void*>(name2) << "\n";

To fix your code you'll need to implement a copy constructor, assignment operator and destructor, see What is The Rule of Three? or more simply just use std::string which does all of that for you.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
2

You have no explicit implementation of the copy constructor, so the default implementation is used. And the default implementation is shallow: it doesn't copy the string, but copies pointers only. As the result, the first object (s1) creates a new buffer, but the second object (s2) just reuses the pointer of the first one. That is why the addresses of the string are the same and that is why changing the string in one object automatically change the other string. Moreover, you would have a problem is you would try to release the memory: which object should delete the buffer now?

You should follow the rule of 3: implement a custom destructor that releases the memory allocated in your constructor, implement copying constructor and assignment operator. On top of that you may consider moving constructor and moving assignment operator.

user207421
  • 305,947
  • 44
  • 307
  • 483
Dmitry Kuzminov
  • 6,180
  • 6
  • 18
  • 40