Я не понимаю, что происходит. Я только учусь C++, и я вижу что-то вроде этого много:Что такое const & do?
double some_function(const Struct_Name& s) {
...
}
Почему const
если мы проходим по ссылке?
Я не понимаю, что происходит. Я только учусь C++, и я вижу что-то вроде этого много:Что такое const & do?
double some_function(const Struct_Name& s) {
...
}
Почему const
если мы проходим по ссылке?
Ссылка на номер const
предотвращает изменение объекта, поскольку const
будет где-то еще, но также позволяет избежать потенциальной стоимости копирования.
, но сделать ссылку неменяемой глупостью - это всего лишь адрес. вы говорите, что когда этот конкретный бит памяти обращается и читается, что никакие записи не разрешены для данного раздела памяти в рамках этой функции? – lollercoaster
Что-то вдоль этих линий. Передача по ссылке похожа по скорости на передачу указателя, но синтаксис для передачи ссылки const такой же, как и любой другой аргумент (между прочим). Что касается записи, то такое же принуждение может быть применено как к скопированному объекту const, но без подрыва системы, могут быть вызваны только методы const, и вы не можете записать объект.Целью является передача больших объектов без выполнения копии (которая может быть много глубоких копий в случае коллекций), но использовать регулярный синтаксис и обеспечивать стандартную константу. – ssube
@lollercoaster: Это не ссылка, к которой применяется константа, это референт. В любом случае ссылки не могут быть переназначены, поэтому нет смысла создавать их const. Если бы вы могли, это выглядело бы так: '(Struct_Name & const s)' не так: '(const Struct_Name & s)' –
Вызов const-reference позволяет избежать копирования Struct_Name
, обещая не изменять его.
Существует причина как для этой причины, так и для семантики.
Если Struct_Name
большое, копирование дорогостоящего как во времени, так и в памяти.
Если Struct_Name
не подлежит сомнению (или становится недействительным при копировании), вызов по значению невозможен или представляет собой нежелательную сложность. Например: std::unique_ptr
и std::auto_ptr
.
Вы передаете ссылку const, если вы не хотите (или не можете) изменять передаваемый аргумент, и не хотите, чтобы производительность, которую вы могли получить, могла копировать объект.
@ildjarn: вы передаете аргумент копией в вашем случае. –
@eharvest: Мое мнение заключалось в том, что принятие неконстантной ссылкой не позволяет передавать временные данные при выполнении ссылки const. (После всего, OP особо интересуется, какая польза 'const' предлагает, когда вы уже проступаете по ссылке, - это означает, что временные данные являются одним из этих преимуществ.) – ildjarn
Сообщаете компилятору, что вы не собираетесь менять его.
Это позволяет сделать некоторые оптимизации, которые он не смог бы сделать иначе. В принципе, он дает вам ту же семантику, что и передача по значению, но не несет штраф за выполнение вызова конструктора копирования.
Семантика передачи по значению и передачи по const-ссылке не совпадают - в многопоточная среда, последняя не дает никаких гарантий относительно срока жизни объекта, в то время как первая делает. – ildjarn
С помощью const
мы можем сигнализировать как пользователю функции, так и компилятору, что объект, переданный как аргумент s
, не будет изменен внутри функции (что было бы реально, потому что мы передаем его по ссылке!). Компилятор может дать нам ошибку, если мы случайно изменим объект, и он может сделать некоторые оптимизации, которые он не мог сделать иначе.
Дополнительным преимуществом является то, что если вызывающий объект функции имеет только указатель на объект const
, он все равно может предоставить этот объект в качестве аргумента без кастования.
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
};
Использование константного параметра хорошо с точки зрения дизайна, если вы знаете, некоторые функции не должны изменять свой объект, то вы добавить Уста. Это означает, что ни один другой программист не может вносить изменения в некоторые глубоко скрытые в иерархии классов классы, которые изменят ваш объект. Это действительно облегчает отладку.
Еще одна причина, о которой никто еще не упомянул - ссылка на ссылку 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!
Книга, которую вы обучения C++ от не исчерпывающе покрытия [Уст-корректность] (http://en.wikipedia.org/вики/Const-корректность)? – ildjarn
const-correctness _is_ тяжелый и запутанный на C++, но вам действительно нужно учиться и понимать этот материал. Неправильное использование вашего кода не будет компилироваться, и вам будет сложно понять, почему. – cha0site