2011-12-30 2 views
0

Я не понимаю, что происходит. Я только учусь C++, и я вижу что-то вроде этого много:Что такое const & do?

double some_function(const Struct_Name& s) { 
    ... 
} 

Почему const если мы проходим по ссылке?

+2

Книга, которую вы обучения C++ от не исчерпывающе покрытия [Уст-корректность] (http://en.wikipedia.org/вики/Const-корректность)? – ildjarn

+1

const-correctness _is_ тяжелый и запутанный на C++, но вам действительно нужно учиться и понимать этот материал. Неправильное использование вашего кода не будет компилироваться, и вам будет сложно понять, почему. – cha0site

ответ

4

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

+0

, но сделать ссылку неменяемой глупостью - это всего лишь адрес. вы говорите, что когда этот конкретный бит памяти обращается и читается, что никакие записи не разрешены для данного раздела памяти в рамках этой функции? – lollercoaster

+0

Что-то вдоль этих линий. Передача по ссылке похожа по скорости на передачу указателя, но синтаксис для передачи ссылки const такой же, как и любой другой аргумент (между прочим). Что касается записи, то такое же принуждение может быть применено как к скопированному объекту const, но без подрыва системы, могут быть вызваны только методы const, и вы не можете записать объект.Целью является передача больших объектов без выполнения копии (которая может быть много глубоких копий в случае коллекций), но использовать регулярный синтаксис и обеспечивать стандартную константу. – ssube

+1

@lollercoaster: Это не ссылка, к которой применяется константа, это референт. В любом случае ссылки не могут быть переназначены, поэтому нет смысла создавать их const. Если бы вы могли, это выглядело бы так: '(Struct_Name & const s)' не так: '(const Struct_Name & s)' –

2

Вызов const-reference позволяет избежать копирования Struct_Name, обещая не изменять его.

Существует причина как для этой причины, так и для семантики.

Если Struct_Name большое, копирование дорогостоящего как во времени, так и в памяти.

Если Struct_Name не подлежит сомнению (или становится недействительным при копировании), вызов по значению невозможен или представляет собой нежелательную сложность. Например: std::unique_ptr и std::auto_ptr.

4

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

+0

@ildjarn: вы передаете аргумент копией в вашем случае. –

+0

@eharvest: Мое мнение заключалось в том, что принятие неконстантной ссылкой не позволяет передавать временные данные при выполнении ссылки const. (После всего, OP особо интересуется, какая польза 'const' предлагает, когда вы уже проступаете по ссылке, - это означает, что временные данные являются одним из этих преимуществ.) – ildjarn

2

Сообщаете компилятору, что вы не собираетесь менять его.

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

+1

Семантика передачи по значению и передачи по const-ссылке не совпадают - в многопоточная среда, последняя не дает никаких гарантий относительно срока жизни объекта, в то время как первая делает. – ildjarn

2

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

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

1

Const здесь promisses что some_function не будет изменять параметр ы,

double some_function(const Struct_Name& s) { 
    ... 
} 

вы можете попробовать изменить его, но компилятор будет возвращать ошибки. На самом деле, константа требует тщательного написания внутренних методов Struct_Name, т.е. вы не сможете вызвать внутри some_function функции non-const на s-объекте. Вы можете попробовать, но вы получите ошибку. то есть:

struct Struct_Name { 
    void myfun() const { } // can be called from some_function 
    void myfun2() { } // will show error if called from some_function 
}; 

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

1

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

Например:.

void foo(const std::string &s) 
{ 
    ... 
} 

foo("hello"); // OK 

foo() ожидает std::string, но получает const char* вместо этого. Так как std::string имеет конструктор, который принимает const char*, компилятор генерирует код, который эффективно делает это:

std::string temp("hello"); 
foo(temp); 

Компилятор знает параметр const, временный не будет изменен foo(), и временное будет отброшен после того как foo() выходит, поэтому он не жалуется на необходимость создания временного.

То же самое происходит, если параметр передается по значению (const или не- const, это не имеет значения), а не по ссылке:

void foo(const std::string s) 
{ 
    ... 
} 

void bar(std::string s) 
{ 
    ... 
} 

foo("hello"); // OK 
bar("world"); // OK 

Это фактически то же самое, как это:

{ 
std::string temp1("hello"); 
foo(temp1); 
} 

{ 
std::string temp2("world"); 
bar(temp2); 
} 

Опять же, компилятор не жалуется, так как он знает, что временное не влияет на код вызова, и любые изменения, внесенные во временное положение в bar(), будут безопасно удалены.

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

void foo(std::string &s) 
{ 
    ... 
} 

foo("hello"); // warning! 
Смежные вопросы