C++ Player类成员m_name互相覆盖问题咨询
嘿,看了你的代码和问题,我马上就发现问题出在哪了——你的m_name用了std::string_view类型,但这个类型本质上只是个“视图”,它不自己存储字符串内容,只是指向别人的内存空间。
具体来说,你在循环里定义的temp是一个std::string,每次循环都会接收新的用户输入并覆盖它的内容。当你创建Player player0{temp}时,std::string_view会直接指向temp的内存地址。随后你把player0放入playerArray,但这个数组里的Player对象的m_name依然指向temp的内存。
当循环进入下一次迭代,temp被新的名字覆盖时,所有之前创建的Player对象的m_name视图都会看到这个新内容。等到循环结束,temp里存的是最后输入的那个名字,所以你调用playerArray[0].getName()、playerArray[1].getName()时,输出的自然都是最后那个名字,看起来就像是m_name互相覆盖了。
解决方案
最稳妥也最简单的办法,就是把Player类里的m_name类型从std::string_view改成std::string。这样每个Player对象都会自己持有一份名字的副本,各自独立,不会再出现互相影响的情况。修改后的代码大概是这样:
class Player { public: // 保留你的getters/setters Player(std::string name) : m_name{std::move(name)} // 使用std::move避免不必要的拷贝,提升效率 {} private: std::string m_name{ "default" }; // 其他成员保持不变 };
如果你非要坚持用std::string_view(其实这里完全没必要),你得确保每个Player的m_name指向的内存不会被后续修改。比如可以把所有名字存储到一个全局或持久的容器中,让string_view指向这些持久化的内存,但这种做法反而增加了复杂度,远不如直接用std::string省心。
另外,你之前对player0的理解是正确的:每次循环里的player0都是局部变量,循环结束后就会被销毁,但你已经把它的副本(或移动后的对象)存入了playerArray,数组里的Player对象是独立存在的,只是它们的m_name因为string_view的特性才出现了覆盖问题。
备注:内容来源于stack exchange,提问作者Erik

