Разница между константной ссылкой и нормальным параметром - PullRequest
41 голосов
/ 13 апреля 2010
void DoWork(int n);
void DoWork(const int &n);

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

Ответы [ 7 ]

50 голосов
/ 13 апреля 2010

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

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

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

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

EDIT:
В некоторых случаях исходные данные могут быть изменены, как указано Чарльзом Бэйли в его ответе .

49 голосов
/ 13 апреля 2010

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

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

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

1011 * Е.Г. *

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.

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

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

11 голосов
/ 06 февраля 2017

Есть три способа передать значения в функцию

  1. Передать по значению

    void f(int  n){
        n=n+10;
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x<<endl;
    }
    

    Вывод: 3. Недостаток: когда параметр x проходит через функцию f, компилятор создает копию в памяти в формате x. Так что потеря памяти.

  2. Передать по ссылке

    void f(int  &n){
        n=n+10;
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x<<endl;
    }
    

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

  3. Постоянная ссылка

    void f(const int  &n){
        n=n+10; // Error: assignment of read-only reference  ‘n’
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x<<endl;
    }
    

    Вывод: выдается ошибка в n=n+10, потому что когда мы передаем аргумент параметра const reference, тогда это параметр только для чтения, вы не можете изменить значение n.

6 голосов
/ 13 апреля 2010

С

 void DoWork(int n);

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

void DoWork(const int &n);

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

2 голосов
/ 13 апреля 2010

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

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

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

0 голосов
/ 30 августа 2010

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

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

Вот различия

$ 13.1 - «Только внешние и переменные спецификаторы типов на самом внешнем уровень спецификации типа параметра игнорируется таким образом; спецификаторы типа const и volatile, скрытые в типе параметра спецификации важны и могут использоваться для различения объявления перегруженных функций.112). В частности, для любого типа Т, «Указатель на T», «указатель на const T» и «указатель на volatile T» рассматриваются различные типы параметров, как «ссылка на T» «Ссылка на const T» и «ссылка на летучую 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 голосов
/ 13 апреля 2010

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

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

...