Страницы

Поиск по вопросам

суббота, 28 декабря 2019 г.

В чем разница между константой x и &xx?

#cpp


В чем разница между константой x и &xx?

#include 
using namespace std;

int main() {
    const int x = 2;
    const int &xx = 3;
    cout << x << endl;
    cout << xx << endl;
    return 0;
}


Зачем нужен &?
    


Ответы

Ответ 1



Семантически эти два объявления различны 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) a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or Обратите внимание, что указано, что должна иметь место ссылка на константный объект, в то время как временное выражение, которым инициализируется ссылка вышепоказанного фрагмента кода, является не константным. Поэтому компилятор выдает сообщение об ошибке. Этот же фрагмент кода успешно компилируется на www.ideone.com . Этот компилятор, по всей видимости, основывается на другом подпункте данного пункта стандарта C++ a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e; В этом подпункте ничего не говорится про константность литерального временного объекта. Достаточно, чтобы он имел литеральный тип. Так что если покопаться в стандарте C++, а также посмотреть на поведение компиляторов, то различия будут явными.:)

Ответ 2



const int &xx = 3; - это ссылка на константное значение типа int. Откровенно говоря, рассказывать, что такое ссылка в C++, достаточно долго, поэтому позвольте ограничиться этим кратким ответом, отправив вас к соответствующей литературе. Ссылка - это как бы псевдоним переменной, так сказать, альтернативное имя. В вашем конкретном случае поменять значение 3 просто так нельзя - это константа, поэтому и ссылка на это значение допустима только как на const int.

Ответ 3



Разница на уровне машинного кода: 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

Комментариев нет:

Отправить комментарий