Из другого поста я тестирую пример, касающийся функции const X& x. В этой ссылке Что означает «const X & x»? говорится «Это означает, что x является псевдонимом объекта X, но вы не можете изменить этот объект X через x». Но в приведенном ниже примере показано, что мы можем изменить объект X? Почему?

#include <iostream>

using namespace std;

int a = 1;

void DoWork(const int &n)
{
    a = n * 2;  // If n was a reference to a, n will have been doubled
    cout << "n: " << n << endl;

    //f();  // Might change the value of whatever n refers to
}

int main()
{
    DoWork(a);
    cout << "a: " << a << endl;
}

Дополнительный вопрос: например, у нас есть функция, возвращающая константную ссылку, почему она может быть присвоена неконстантной ссылке?

const X& tmp = get();
X& other = tmp; //this works, but why? this get rids of const X& in tmp?

c++
0
coder 16 Ноя 2019 в 07:05

2 ответа

Лучший ответ

Я думаю, что у вас есть путаница о const и ссылках. Во-первых, что такое ссылка

это другое имя (псевдоним) для объекта.

То, что написано в параметрах функции, означает, что n является ссылкой на const. Это означает, что вы не можете изменить a на n. (Или, в простом смысле, n не может быть слева от оператора присваивания. Это также означает, что n привязан к объекту навсегда.

n = n+2; // This is an error as n is const and hence you can't use n to modify the object it is pointing.
a = n+2; // here you are not using `n` to modify. So this is ok.
int x = 10 ;
n = x; // error as n is bounded to `a` so it can't be bounded again to any other variable x. You can see `n` is on left which is an error.

Теперь, если вы делаете это

cout<<a<<"\t"<<n<<endl; // Output 3; (1+2)

О последующем вопросе. (Внимательно прочтите) Давайте предположим общий сценарий.

const int ci = 1024;
int &r2 = ci;  // error: non const reference to a const object

То же самое относится и к вашему функциональному вопросу. Вы, должно быть, удивляетесь, почему мы не можем сделать такую вещь. Смотрите здесь, c1 - const, поэтому мы не можем его изменить. Теперь предположим (просто предположить), что следующий код был бы юридическим кодом. Тогда r2 будет ссылкой на c1. Теперь, как я уже говорил, ссылка - это другое имя объекта. Это означает, что если мы сделаем арифметику на r2, это будет сделано на ci. r = r+2; // it means ci = ci + 2 ; но смотри ci был const (его не следует изменять, но мы его изменили) Поэтому нам нужно сделать что-то вроде.

const int ci = 1024;
const int &r2 = ci;  // error: non-const reference to a const object

Это гарантирует, что мы не можем сделать r = r +2;, который обеспечивает / сохраняет постоянство ci.

Get () возвращает const, поэтому, чтобы сохранить его, переменная, используемая для получения от функции, должна быть const. Итак, часть, которую вы сказали, работает как ошибка в соответствии со стандартом, может быть, это расширение вашего компилятора.

2
Problematic Dude 16 Ноя 2019 в 05:18

Имейте в виду, что const X& по сути означает, что компилятор накладывает ограничение на то, что вы не можете изменить ссылку на значение через ссылку (как говорит страница, на которую вы ссылаетесь). Фактическое значение , на которое ссылается ссылка, чисто определяется во время выполнения, и компилятор не может сделать вывод, что вы изменяете значение, на которое ссылается x, когда он видит строку a = n * 2;.

Небольшое изменение в вашем коде может помочь в том, что происходит,

#include <iostream>

using namespace std;

int a = 1;
int b = 1; // new variable

void DoWork(const int &n)
{
    a = n * 2;  // If n was a reference to a, n will have been doubled
    cout << "n: " << n << endl;

    //f();  // Might change the value of whatever n refers to
}

int main()
{
    // Whether `x` in `DoWork` refers to `b` or `a` is purely determined at runtime.
    if (rand() % 2 == 0)
        DoWork(a);
    else
        DoWork(b);

    cout << "a: " << a << endl;
}

Другими словами, компилятор не может быть уверен в том, на какие значения будут ссылаться ссылки. В C ++ ссылки могут даже указывать на недопустимую память,

int *a = 0;
int &ref = *a;
cout << ref; // runtime error

Надеюсь это поможет.

Изменить: Что касается вопроса о том, какой компилятор вы используете? Любой стандартный компилятор откажется компилировать код.

2
user3335 16 Ноя 2019 в 05:01