Подтвердить что ты не робот

Почему это компилируется? Ожидание "не может назначить константу неконстантной ссылке"

Интервьюер показал мне такой код и спросил меня, будет ли он компилироваться и давать мои рассуждения. Я сказал ему очень уверенно, что он не будет компилироваться, потому что 10 является константой, и вы не можете назначить константу неконстантной ссылке (например, int & b = 10 не будет компилироваться), также _a является временной переменной, и она также рассматривается const, опять же, вы не можете использовать неконстантную ссылку для ссылки на константную переменную.

Однако после того, как я пришел к своему удивлению, я нашел, что он отлично компилируется со всеми возможными компиляторами. Кроме того, я не получил работу. Какая часть моего понимания пошла не так?

class A {
    int& a;
public:
    A(int _a):a(_a) {}
};

int main() {
    A a(10);
}    
4b9b3361

Ответ 1

нет никакого "присваивания" константы с этим кодом...

Код вызывает конструктор, который принимает int и, в свою очередь, вызывает инициализатор int&. Вы пропустили несколько шагов, которые компилятор видит/принимает, когда вы предполагали, что это означает int& b = 10, в то время как это больше похоже на _a = 10; int& a = _a;. он компилируется, но это совершенно не так, как вы хотели бы использовать (привязка ссылки к стеку, которая позже приведет к поведению/повреждению undefined)...

Ответ 2

_a - временная переменная, и она также считается const,

Неправильно. В области тела конструктора и списка инициализаторов он не является временным. Это аргумент lvalue и function - он длится далеко от вашего единственного использования для всего тела функции.

Кроме того, rvalues ​​и const не имеют абсолютно никакого отношения друг к другу, за исключением того, что в С++ 03 вы не можете связывать неконстантные ссылки на rvalues. Например, вы можете называть множество неконстантных функций на rvalues ​​просто.

Этот код прямо эквивалентен

int main() {
    int i = 10;
    int& x = i;
}

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

Ответ 3

Это будет привязано к стеку, потому что аргументы функции могут быть привязаны к ссылке. это, однако, не является безопасным вообще и вызовет поведение undefined и повреждение стека в какой-то момент.

Ответ 4

Есть 2 вопроса этой проблемы.

q1) должен ли он компилироваться или нет?

Ans: он будет скомпилирован, потому что здесь a относится к _a, это не компиляторная головная боль, как _a получит данные.

q2) Правильный код? Я имею в виду, будет ли какая-либо ошибка времени выполнения или нет?

Ans: Это неправильный код. Здесь a относится к _a, которая является переменной стека. Поэтому, если вы используете переменную-ссылочную переменную, используя объект класса A, вывод будет непредсказуемым. Давайте возьмем пример, приведенный ниже:

class A { 
public:
    int& a; 

    A(int _a):a(_a) {} 
}; 

int main() { 
    A a(10); 
    A a1(11); 
    cout << a.a;
}    

См. вывод. Выход непредсказуем, потому что вы пытаетесь получить доступ к ссылочной переменной a, которая ссылается на переменную стека конструктора