Значение внутри объекта не изменится после передачи по ссылке - PullRequest
0 голосов
/ 05 апреля 2020

Почему значение внутри объекта не меняется, хотя я передал по ссылке.

class ref_test {
public:
    explicit ref_test(const int& a) : a(a) {};

    const int& get_a() noexcept { return a;}
private:
    const int a;
};

int main(int argc, char* argv[]) {

    int b = 10;
    ref_test r(b);

    b = 15;
    std::cout << r.get_a() << std::endl;
    std::cout << b << std::endl;

    return 0;
}

Вывод:
10
15

Насколько я понимаю, я передать ячейку памяти объекту, которому запрещено изменять его (поскольку он помечен как const). Если я затем изменю значение после передачи, значение в ячейке памяти должно измениться, и поэтому должно измениться и значение внутри объекта. Если это так, передача по ссылке не должна быть безопасной для передачи объекту, поскольку впоследствии значение может быть изменено. Следовательно, лучше ли передавать по значению объекту?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2020

Внутри класса ref_test закрытый элемент данных a не имеет ссылочного типа

const int a;

Если вы хотите, чтобы этот элемент данных имел ссылочный тип, вы должны написать

const int &a;

В этом случае элемент данных a будет ссылаться на объект, переданный конструктору класса.

Чтобы увидеть изменения, вставьте еще один выходной оператор перед переназначением переменной b.

std::cout << r.get_a() << std::endl;
b = 15;
std::cout << r.get_a() << std::endl;

Другой подход заключается в использовании стандартного класса std::reference_wrapper.

Вот демонстрационная программа.

#include <iostream>
#include <functional>

class ref_test 
{
public:
    explicit ref_test(const int& a) : a(a) {};

    const int & get_a() noexcept { return a;}

private:
    const int &a;
};

class ref_test2 
{
public:
    explicit ref_test2( const int& a ) : a(a) {};

    const int & get_a() noexcept { return ( a.get() );}

private:
    std::reference_wrapper<const int> a;
};

int main() 
{
    int b = 10;
    ref_test r(b);

    std::cout << r.get_a() << '\n';
    std::cout << b << '\n';

    b = 15;

    std::cout << r.get_a() << '\n';
    std::cout << b << '\n';

    std::cout << '\n';

    ref_test2 r2( b );

    std::cout << r2.get_a() << '\n';
    std::cout << b << '\n';

    b = 20;

    std::cout << r2.get_a() << '\n';
    std::cout << b << '\n';

    return 0;
}

Вывод программы:

10
10
15
15

15
15
20
20
0 голосов
/ 05 апреля 2020

Закрытое int внутри класса не является ссылкой. Таким образом, конструкция в инициализаторе члена - это копирование аргумента.

Если вы измените переменную-член на

int const &a;

, тогда программа напечатает 15 15

Если это не то поведение, которое вам нужно, просто примите аргумент конструктора по значению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...