В чем разница между константой x и &xx?
#include <iostream>
using namespace std;
int main() {
const int x = 2;
const int &xx = 3;
cout << x << endl;
cout << xx << endl;
return 0;
}
Зачем нужен &
?
Семантически эти два объявления различны
const int x = 2;
const int &xx = 2;
В первом случае объявляется константный объект, который инициализируется целочисленным литералом. Для него может даже не выделяться память, если не требуется обращение к памяти объекта. Компилятор может использовать значение этого константного объекта на этапе компиляции. Например,
const int x = 2;
int a[x];
Размер объявленного массива известен на этапе компиляции.
Что касается данного объявления
const int &xx = 2;
то здесь сначала создается временный объект для значения выражения 2
, и затем на этот временный объект определяется ссылка. Где разместится в памяти этот временный объект - это будет известно на этапе выполнения программы. Заметьте, что сам временный объект не является константным. Это просто результат вычисления выражения, состоящего из одного операнда - целочисленного литерала 2.
В связи с этим имеется различная реакция компиляторов на использование ссылки xx
.
Так, например, компилятор MS VC 2016 Community не компилирует следующий фрагмент кода
const int &xx = 2;
int a[xx];
Сообщение об ошибке
Ошибка C2131 выражение не определяется константой 623
Как я думаю, MS VC++ 2016 Community в данном случае ориентируется на следующее положение стандарта C++ о константных выражениях (5.20 Constant expressionю, п. №2)
Обратите внимание, что указано, что должна иметь место ссылка на константный объект, в то время как временное выражение, которым инициализируется ссылка вышепоказанного фрагмента кода, является не константным. Поэтому компилятор выдает сообщение об ошибке.
Этот же фрагмент кода успешно компилируется на www.ideone.com . Этот компилятор, по всей видимости, основывается на другом подпункте данного пункта стандарта C++
В этом подпункте ничего не говорится про константность литерального временного объекта. Достаточно, чтобы он имел литеральный тип.
Так что если покопаться в стандарте C++, а также посмотреть на поведение компиляторов, то различия будут явными.:)
const int &xx = 3;
- это ссылка на константное значение типа int
. Откровенно говоря, рассказывать, что такое ссылка в C++, достаточно долго, поэтому позвольте ограничиться этим кратким ответом, отправив вас к соответствующей литературе.
Ссылка - это как бы псевдоним переменной, так сказать, альтернативное имя. В вашем конкретном случае поменять значение 3 просто так нельзя - это константа, поэтому и ссылка на это значение допустима только как на const int
.
Разница на уровне машинного кода:
gcc 6.x
// const int x = 2;
mov DWORD PTR [rbp-4], 2
// const int &xx = 3;
mov eax, 3
mov DWORD PTR [rbp-20], eax
lea rax, [rbp-20]
mov QWORD PTR [rbp-16], rax
gcc 4.5.x
// const int &xx = 3;
mov DWORD PTR [rbp-8], 3
lea rax, [rbp-8]
mov QWORD PTR [rbp-16], rax
Очевидно, что вторая инструкция [const int &xx = 3;
] более дорогая, нежели первая. Ваш кэп.
Массив размером с x ? Пожалуйста. Ни одной ассемблерной инструкции - при условии, что мы его в дальнейшем никак не используем.
Массив размером с xx при условии, что мы его никак не используем. Пожалуйста.
// gcc 6.x - int arr[xx];
// комментарии излишне
mov rax, QWORD PTR [rbp-16]
mov eax, DWORD PTR [rax]
cdqe
sub rax, 1
mov QWORD PTR [rbp-24], rax
mov rax, QWORD PTR [rbp-16]
mov eax, DWORD PTR [rax]
cdqe
mov r8, rax
mov r9d, 0
mov rax, QWORD PTR [rbp-16]
mov eax, DWORD PTR [rax]
cdqe
mov rsi, rax
mov edi, 0
mov rax, QWORD PTR [rbp-16]
mov eax, DWORD PTR [rax]
cdqe
sal rax, 2
lea rdx, [rax+3]
mov eax, 16
sub rax, 1
add rax, rdx
mov edi, 16
mov edx, 0
div rdi
imul rax, rax, 16
sub rsp, rax
mov rax, rsp
add rax, 3
shr rax, 2
sal rax, 2
mov QWORD PTR [rbp-32], rax
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Читал на английском, но так и не смог разобраться
Реализовать иерархию классовВ каждом производном классе присутствует - конструктор инициализации, методы ввода-вывода данных, метод вычисления...