Различие между константой ссылочный и нормальный параметр

void DoWork(int n);
void DoWork(const int &n);

Какая разница?

47
задан today 26 September 2018 в 01:59
поделиться

6 ответов

Разница более заметна, когда вы передаете большую структуру / класс.

struct MyData {
    int a,b,c,d,e,f,g,h;
    long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);

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

в обоих случаях исходные данные не могут быть изменены изнутри функции.

РЕДАКТИРОВАТЬ:
В некоторых случаях исходные данные могут быть изменены, как указано Чарльзом Бейли в его ответе .

58
ответ дан 7 November 2019 в 12:58
поделиться

Важное отличие состоит в том, что при передаче по ссылке const новый объект не создается. В теле функции параметр фактически является псевдонимом для переданного объекта.

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

Есть принципиальные различия.Если параметр является ссылкой const , но переданный объект на самом деле не был const , то значение объекта может быть изменено во время самого вызова функции.

Например.

int a;

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

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

int main()
{
    DoWork(a);
}

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

например.

void DoWork(const int &n)
{
    const_cast<int&>(n) = 22;
}

Это привело бы к неопределенному поведению, если бы переданный объект был на самом деле const .

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

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

55
ответ дан 7 November 2019 в 12:58
поделиться

Поскольку никто из вас ничего не упомянул о ключевом слове const ...

Ключевое слово const изменяет тип объявления типа или тип параметра функции, предотвращая изменение значения. (Источник: MS)

Другими словами: передача параметра по ссылке делает его доступным для модификации вызываемым объектом. Использование ключевого слова const предотвращает изменение.

2
ответ дан 7 November 2019 в 12:58
поделиться

С

 void DoWork(int n);

n является копией значения фактического параметра, и изменение значения n является допустимым. внутри функции. С

void DoWork(const int &n);

n является ссылкой на фактический параметр, и изменение его значения является незаконным.

6
ответ дан 7 November 2019 в 12:58
поделиться

Первый метод передает n по значению, т.е. копия n отправляется функции. Второй передает n по ссылке, что в основном означает, что указатель на n , с которым вызывается функция, отправляется в функцию.

Для целочисленных типов, таких как int , нет смысла передавать как константную ссылку, поскольку размер ссылки обычно такой же, как размер ссылки (указателя). В случаях, когда создание копии обходится дорого, обычно лучше использовать константную ссылку.

0
ответ дан 7 November 2019 в 12:58
поделиться

Во-первых, не существует концепции ссылок с уточнением cv. Таким образом, термин «ссылка на константу» неверен и обычно используется для описания «ссылки на константу». Лучше начать говорить о том, что имеется в виду.

$8.3.2/1- "Ссылки с квалификацией Cv имеют неправильный формат, за исключением случаев, когда квалификаторы cv вводятся с помощью typedef (7.1.3) или аргумента типа шаблона (14.3), и в этом случае квалификаторы cv игнорируются."

Вот различия

$13.1 - "Только константные и изменчивые спецификаторы типов на самом внешнем уровень спецификации типа параметра таким образом игнорируется; const и volatile спецификаторы типов, спрятанные внутри типа параметра спецификации являются важными и могут быть использованы для различения объявления перегруженных функций.112). В частности, для любого типа T «указатель на T», «указатель на const T» и «указатель на volatile T» считаются отдельными типами параметров, как и «ссылка на T», «ссылка на const T» и «ссылка на volatile T».

void f(int &n){
   cout << 1; 
   n++;
}

void f(int const &n){
   cout << 2;
   //n++; // Error!, Non modifiable lvalue
}

int main(){
   int x = 2;

   f(x);        // Calls overload 1, after the call x is 3
   f(2);        // Calls overload 2
   f(2.2);      // Calls overload 2, a temporary of double is created $8.5/3
}
0
ответ дан 7 November 2019 в 12:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: