提问者:小点点

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


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

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

>

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

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

    在main函数中添加元素“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 << " ";
    }
    

  • 共3个答案

    匿名用户

    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的成员。 从方法返回的是一个副本。

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

    添加“M0”的对象在此行之后:

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

    它的生命结束了。 你得想方设法再见到它。 在再次向成员添加“F0”之后,对get_name0()的下一次调用将为您提供该成员的新副本。

    匿名用户

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

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

    vector<string>& get_name0() {  
    

    匿名用户

    您的函数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中的向量。 如果要修改vectorindnp0,则get_name0应通过引用返回。

    vector<string>& get_name0();
    

    注意,使用get_name0,您将授予类的客户端对数据成员的完全访问权限。 如果只希望客户端读取数据,则使返回的vectorconst

    const vector<string>& get_name0();
    

    或者完全删除该函数,只提供所需的成员修改函数(例如add_name)。