c++ 默认构造函数中数组的地址相同,但打印出来时不同

dgjrabp2  于 2023-08-09  发布在  其他
关注(0)|答案(2)|浏览(104)
#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();
}

字符串
输出:-

0x61ff0b
0x61ff04
0x61fefc
20 ebcd
20 ebcd


为什么s1.name和s2.name的地址不同,并且s2.name中的更改仍会影响s1.name??

vx6bjr1n

vx6bjr1n1#

您正在打印指针变量的地址,而不是指针本身的值。
我们可以将示例简化为:

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

字符串
这将打印两个不同变量的两个不同地址,但我们仍然只有一个数组。
如果你想打印数组的地址,你需要强制转换为void*,因为当传入char*时,流操作符会故意打印以null结尾的字符串的内容:

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


要修复你的代码,你需要实现一个复制构造函数,赋值运算符和析构函数,参见What is The Rule of Three?或更简单的使用std::string,它可以为你完成所有这些。

gwbalxhn

gwbalxhn2#

您没有复制构造函数的显式实现,因此使用默认实现。默认的实现是shallow:它不复制字符串,只复制指针。结果,第一个对象(s1)创建了一个新的缓冲区,但第二个对象(s2)只是重用了第一个对象的指针。这就是为什么字符串的地址是相同的,这就是为什么改变一个对象中的字符串会自动改变另一个字符串的原因。此外,你会遇到一个问题,那就是你会尝试释放内存:哪个对象现在应该删除缓冲区?
你应该遵守规则3:实现一个自定义析构函数来释放在构造函数中分配的内存,实现复制构造函数和赋值运算符。最重要的是,你可以考虑移动构造函数和移动赋值运算符。

相关问题