类成员函数返回私有变量副本后修改异常的原因咨询
你这里的核心误解有两个,咱们一步步拆解清楚:
第一个误区:成员函数里的name不是本地副本!
在get_name0()函数里,你直接写name.push_back("f0"),这里的name不是私有成员的本地副本,而是直接访问当前类对象的私有成员变量!因为在类的非静态成员函数中,默认可以直接操作当前对象的成员变量,不需要额外声明。所以第一次调用np0.get_name0()时,你其实是给np0对象的私有name添加了"f0",这也是为什么你看到对象的name变成了{ab, f0}。
第二个误区:返回的副本是临时对象,修改它不会影响原成员
当你执行np0.get_name0().push_back("m0")时,get_name0()会返回一个临时的vector<string>副本(从当前对象的name复制而来)。你给这个临时副本添加了"m0",但这个临时对象在这条语句执行完之后就会被销毁,完全不会影响np0对象里的私有name变量。
为什么最终输出是{ab, f0, f0}?
当你第二次调用np0.get_name0()时,函数又一次执行了name.push_back("f0")——也就是再次给np0的私有name添加了"f0",此时对象的name就变成了{ab, f0, f0},然后返回这个副本,你遍历输出的就是这个结果。
如何实现你预期的行为?
如果你想让get_name0()操作的是本地副本(这种场景较少见,因为副本是局部的),需要显式创建私有成员的本地副本:
class Name_pairs { public: vector<string> get_name0() { vector<string> local_name = name; // 显式创建私有成员的本地副本 local_name.push_back("f0"); // 修改的是本地副本,而非原成员 return local_name; } private: vector<string> name = {"ab"}; };
如果你的需求是让外部能直接修改对象的成员,应该提供返回引用的成员函数(注意区分const和非const版本):
class Name_pairs { public: // 返回非const引用,允许外部修改原成员 vector<string>& get_name() { return name; } // 返回const引用,用于const对象,仅允许只读访问 const vector<string>& get_name() const { return name; } private: vector<string> name = {"ab"}; };
这样在main里调用np0.get_name().push_back("m0"),就会直接修改np0的私有成员了。
内容的提问来源于stack exchange,提问作者Theodore

