为什么成员函数不能修改主函数变量的本地副本?

Why a member function cannot modify the local copy of the variable from the main function?

我正在尝试了解 class 的成员函数在创建 class 的本地副本时的行为方式 私有变量。 (通过引用访问时不是)

所以我有这段代码,我的理解是这样的:

  1. 在成员函数 get_name0() 中,向量 "name" 是私有数据成员 "name".

    [= 的本地副本27=]
  2. 在 get_name0() 函数中添加元素 "f0" 应该使对象 np0 具有 {ab, f0} 并且确实如此。没问题。

  3. 在主函数中添加元素 "m0" 应该使(?)对象 np0 具有 {ab, f0, m0} 但取而代之的是 {ab, f0, f0} .我不明白为什么会这样,可能我哪里错了?

提前感谢任何为我澄清这一点的人!

class Name_pairs
{
public:
    vector<string> get_name0() // this is a member function that returns a copy; name is a local copy
    {
        name.push_back("f0"); // the copy can be changed by the member function
        return name;          
    }

private:
    vector<string> name = {"ab"};
};

int main()
{
    Name_pairs np0;
    np0.get_name0().push_back("m0"); // this should change the local copy not the "name" object but it doesn't
    cout << "\nnp0 object: ";
    for (string s : np0.get_name0())   // this should print the local copy from the inside of get_name0() function
        cout << s << " ";
}

get_name() returns 会员的副本。两个不同的调用 return 成员的两个不同副本。

这将产生预期的输出:

int main()
{
    Name_pairs np0;
    auto name = np0.get_name0();
    name.push_back("m0");
    cout << "\nnp0 object: ";
    for (string s : name)
        cout << s << " ";
}

在您的代码中没有 "local copy"。向量 returned 是一个临时变量,在语句结束时不再存在。

  1. Inside the member function get_name0() the vector "name" is a local copy of the private data member "name".

没有。在成员函数 name 内部是名为 name 的成员。你return从方法中得到的是一个副本。

  1. Adding the element "f0" inside the get_name0() function should make the object np0 to have {ab, f0} and it does. No problem here.

没问题,但您是在添加成员,而不是某些 "local copy"。您先添加然后复制(以及 return 方法中的副本)。

  1. Adding the element "m0" in the main function should make(?) the object np0 to have {ab, f0, m0} but instead it has {ab, f0, f0}.

您添加 "m0" 的对象在这一行之后消失了:

np0.get_name0().push_back("m0");

它的生命周期结束了。你必须再次看到它。再次向成员添加 "f0" 后,下一次调用 get_name0() 将为您提供该成员的新副本。

每次调用 get_name0 都会将值 f0 添加到 name 向量中。由于您对该函数有 2 次调用,因此您会插入 2 个 f0 副本。注意range-for循环中的用法也是对这个函数的调用。

但是,由 get_name0 编辑的向量 return 是 name 向量的 copy,因此向该副本添加一个元素不会改变成员变量。如果你想真正改变成员,你需要通过引用 return 向量,像这样:

vector<string>& get_name0() {  

你的函数 get_name0 returns 按值,而不是按引用,所以在你的情况下你的

np0.get_name0().push_back("m0");

表现得像

{
    vector<string> temporary = np0.get_name0();
    temporary.push_back("m0");
}   //  here temporary is destroyed

您的 push_back("m0"); 只修改临时的,而不是 np0 中存储的 vector。如果你想修改 vectornp0 那么 get_name0 应该 return 参考。

vector<string>& get_name0();

请注意,使用 get_name0 您将授予 class 的客户对数据成员的完全访问权限。如果您只希望客户端读取数据,则将 returned vector const

const vector<string>& get_name0();

或者完全删除该功能,只提供您需要的成员修改功能(例如add_name)。