为什么我可以更改作为常量引用传递的对象的成员?

时间:2018-07-14 07:00:31

标签: c++ oop

class Student {
private:
    int age;
public:
    char *name;
    Student(int age,char*name) {
        this->age=age;
        this->name=new char[strlen(name)+1];
        strcpy(this->name,name);
    }
    Student(Student const &s1) {
        this->age=s1.age;
        this->name=new char[strlen(s1.name)+1];
        strcpy(this->name,s1.name);
        s1.name[0]='x';
    }
    void display() {
        cout<<age<<" "<<name<<endl;
    }
};
int main() {
    char name[]="abcd";
    Student s1(10,name);
    s1.display();
    Student s2(s1);
    s2.name[0]='x';
    s1.display();
    s2.display();
}

我已经将s1作为常量引用传递了,但是我能够更改s1.name [0]并且程序成功编译。为什么我可以更改s1.name [0]?enter image description here

2 个答案:

答案 0 :(得分:2)

您没有修改s1。您修改了一些无关的内存块(由new分配),s1持有一个指针。在C ++中,原始指针与其可能指向的任何内存块之间没有特殊关系。

如果使用std::string代替原始指针和手动内存管理,则不会出现此问题。

答案 1 :(得分:0)

正如其他人已经说过的那样,这是因为s1是const,所以您不能修改指针s1.name。但是,s1.name指向的内存不是常量。

如果您真的不能使用std::string,则可能需要看看std::experimental::propagate_const。这是任何指针类型的包装,在您的情况下为原始指针,顾名思义,它将将其常数传播到它所指向的内存中。

但是,我几乎无法想象在任何情况下都无法/不允许使用std类(string),但是可以使用std::experimental类,这很可能不是您的选择。但是,您可能会受到这个想法的启发,并编写自己的字符串类。

请注意,以防万一:delete缺少相应的newstd::string会为您做到这一点。因此,如果您编写自己的字符串类,请确保也要这样做。