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

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

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

Ответ 1

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

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:
В некоторых случаях исходные данные могут быть изменены в соответствии с Чарльзом Бейли в его ответе .

Ответ 2

Важным отличием является то, что при передаче по ссылке 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, тогда функция могла (даже если это не рекомендуется) изменить его значение с помощью cast.

например.

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

Это приведет к поведению undefined, если объект, переданный в действительности, был фактически const.

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

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

Ответ 3

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

  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, потому что, когда мы передаем аргумент константного ссылочного параметра, тогда это параметр только для чтения, вы не можете изменить значение n.

Ответ 4

С

 void DoWork(int n);

n - это копия значения фактического параметра, и законно изменить значение n внутри функции. С помощью

void DoWork(const int &n);

n - это ссылка на фактический параметр, и нецелесообразно изменять его значение.

Ответ 5

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

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

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

Ответ 6

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

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

Ответ 7

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

$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
}