Почему функция-член не может изменять локальную копию переменной из основной функции? - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь понять, как ведет себя функция-член класса при создании локальной копии частной переменной. (Не при доступе к нему по ссылке)

Итак, у меня есть этот код, и я понимаю следующее:

  1. Внутри функции-члена get_name0 () "имя" вектора локальная копия частного элемента данных «name».

  2. Добавление элемента «f0» внутри функции get_name0 () должно привести к тому, что объект 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 << " ";
}

Ответы [ 3 ]

3 голосов
/ 19 июня 2020

Каждый вызов get_name0 добавляет значение f0 к вектору name. Поскольку у вас есть 2 вызова этой функции, вы вставляете 2 копии f0. Обратите внимание, что использование в диапазоне l oop также является вызовом этой функции.

Однако вектор, возвращаемый get_name0, является копией из name вектор, поэтому добавление элемента к этой копии не изменит переменную-член. Если вы действительно хотите изменить член, вам нужно вернуть вектор по ссылке, например:

vector<string>& get_name0() {  
1 голос
/ 19 июня 2020

Ваша функция 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"); изменяет только временное, а не vector, хранящийся в np0. Если вы хотите изменить vector ind np0, тогда get_name0 должен возвращаться по ссылке.

vector<string>& get_name0();

Позаботьтесь о том, чтобы с get_name0 вы предоставляли клиентам вашего класса полный доступ к данным член. Если вы хотите, чтобы клиенты только читали данные, сделайте возвращаемый vector const

const vector<string>& get_name0();

Или удалите функцию вообще и предоставьте только те функции модификации, которые вам нужны (например, add_name для пример).

1 голос
/ 19 июня 2020

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. То, что вы возвращаете из метода, является копией.

Добавление элемента «f0» внутри функции get_name0 () должно сделать объект np0 имеющим {ab, f0}, и это так. Здесь нет проблем.

Здесь нет проблем, но вы добавляете к члену, а не к какой-то «локальной копии». Сначала вы добавляете, затем копируете (и возвращаете копию из метода).

Добавление элемента «m0» в основную функцию должно сделать (?) Объект np0 иметь {ab, f0, m0}, но вместо этого он имеет {ab, f0, f0}.

Объект, к которому вы добавляете "m0", исчезает после этой строки:

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

Его время жизни закончилось. Вы должны найти способ увидеть это когда-нибудь снова. Следующий вызов get_name0() даст вам новую копию участника после повторного добавления "f0" к члену.

...