【问题标题】:Why a member function cannot modify the local copy of the variable from the main function?为什么成员函数不能从主函数修改变量的本地副本?
【发布时间】:2020-06-19 12:34:10
【问题描述】:

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

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

  1. 在成员函数 get_name0() 中,向量“name”是私有数据成员“name”的本地副本。

  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 << " ";
}

【问题讨论】:

    标签: c++ member-functions


    【解决方案1】:

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

    但是,get_name0 返回的向量是name 向量的副本,因此向该副本添加元素不会更改成员变量。如果要实际更改成员,则需要通过引用返回向量,如下所示:

    vector<string>& get_name0() {  
    

    【讨论】:

      【解决方案2】:

      get_name() 返回成员的副本。两个不同的调用返回成员的两个不同副本。

      这将产生预期的输出:

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

      在您的代码中没有“本地副本”。返回的向量是一个临时的,在语句结束时不再存在。

      1. 在成员函数 get_name0() 中,向量“name”是私有数据成员“name”的本地副本。

      没有。在成员函数name 内部是名为name 的成员。您从该方法返回的是一个副本。

      1. 在 get_name0() 函数中添加元素“f0”应该使对象 np0 具有 {ab, f0} 并且确实如此。这里没问题。

      这里没问题,但是您要添加到成员,而不是某些“本地副本”。您先添加然后复制(并从方法返回副本)。

      1. 在主函数中添加元素“m0”应该使(?)对象 np0 具有 {ab, f0, m0} 但它具有 {ab, f0, f0}。

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

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

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

      【讨论】:

      • 感谢 idclev!现在我明白了我的错误……我没有打印新的“名称”,而是打印了另一个对 np0.get_name0() 的调用,就像你说的那样,这是一个新副本……非​​常感谢您纠正我对它的理解意味着退回一份!
      【解决方案3】:

      您的函数 get_name0 按值返回,而不是按引用返回,所以在您的情况下是您的

      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。如果你想修改vector ind np0 那么get_name0 应该通过引用返回。

      vector<string>& get_name0();
      

      请注意,使用get_name0,您将授予您班级的客户对数据成员的完全访问权限。如果你只想让客户端读取数据,那么返回的vectorconst

      const vector<string>& get_name0();
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-24
        • 2011-11-15
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        相关资源
        最近更新 更多