Почему это компилируется? Ожидание "не может назначить константу неконстантной ссылке"
Интервьюер показал мне такой код и спросил меня, будет ли он компилироваться и давать мои рассуждения. Я сказал ему очень уверенно, что он не будет компилироваться, потому что 10 является константой, и вы не можете назначить константу неконстантной ссылке (например, int & b = 10 не будет компилироваться), также _a является временной переменной, и она также рассматривается const, опять же, вы не можете использовать неконстантную ссылку для ссылки на константную переменную.
Однако после того, как я пришел к своему удивлению, я нашел, что он отлично компилируется со всеми возможными компиляторами. Кроме того, я не получил работу. Какая часть моего понимания пошла не так?
class A {
int& a;
public:
A(int _a):a(_a) {}
};
int main() {
A a(10);
}
Ответы
Ответ 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, которая ссылается на переменную стека конструктора