Если вы посмотрите на этот код,
int x = 0;
function(x);
std::cout << x << '\n';
вы не сможете проверить с помощью каких-либо средств синтаксиса, этот параметр x передается по ссылке или что он передается по значению. Единственный способ, которым вы наверняка знаете, - это посмотреть на объявление функции или определение функции.
Вот простой пример того, как я считаю, что это может быть проблемой:
std::string Lowercase(std::string str); //<- this is hidden away in code; probably in a different file.
int main(){
std::string str = "HELLO";
Lowercase(str);
std::cout << str << '\n'; //<- Bug! we expected to output "hello". The problem is not very easy to spot, especially when a function name sounds as though it will change the passed in value.
}
Чтобы избежать необходимости переходить между вызовом функции и объявлением функции (или, в некоторых случаях, документацией), чтобы понять поведение функции, есть способ явно документировать синтаксис вызова функции, который параметр, как ожидается, изменится (т.е. опорный параметр) или что копия отправляется (т.е. передается по значению)?
Я понимаю, что существует также возможность прохождения через const & который имеет аналогичное понятие о передаче по значению, в том, что переменная, переданная внутри, не будет иметь своего значения после вызова функции.
Я уверен, что на языке есть всевозможные ситуации, которые могут добавить к сложности понимания того, как передается параметр, но мне любопытно, есть ли способ бороться с этой проблемой так, как я хочу?
Я заметил, что некоторые люди пишут две подобные функции. Один из них принимает параметр значения, другой - указатель. Это позволяет вызывать такую функцию:
Lowercase(str); //we assume the value will not change
Lowercase(&str); //we assume the value will change
Но это решение имеет много других проблем, и я не хотел бы терять пользу ссылок. Кроме того, мы по-прежнему делаем предположения о поведении.