Всем известно, что аргументы функции C/C++ передаются по значению. Итак, почему некоторые люди настаивают на том, что правильный стиль заключается в создании локальной копии аргумента функции перед его модификацией? Например, они пишут:
void baz(unsigned int *ptr)
{
unsigned int *lPtr = ptr;
for(int i = 0; i < 10; i++)
{
foo(*lPtr++);
}
}
вместо:
void baz(unsigned int *ptr)
{
for(int i = 0; i < 10; i++)
{
foo(*ptr++);
}
}
Похоже, что второй способ легче читать, поскольку он является одним менее переменным.
Единственное оправдание для гораздо больших функций, кто-то может добавить новую функциональность в нижней части функции, не понимая, что параметр был изменен или сделан недопустимым ранее.
Представить:
int bighorriblefunction(const char * astr)
{
// hundreds of lines of horribleness
while ( * astr ) { /* something */ ++ astr ; }
// more pages of code
/** author two adds later */
if ( ! strcmp(astr, "magicvalue") ) { /** do this really important thing **/ return 1 ; }
return 0 ;
}
Его попытка взять автора два в то время, чтобы понять, что новый код никогда не будет работать.
Они делают это, потому что исходное значение полезно при отладке.
Это версия бедного человека о разделении интерфейса от реализации.
Предположим, вы написали этот код год назад:
class Foo
{
public:
void bar( const char *where )
{
// The dreaded copy
const char *destination = where;
// The actual implementation that in the real world may take 500
// lines of code with 20 references to the variable destination
}
};
И теперь, через год, вы хотите сделать параметр, где optional, по умолчанию - переменная-член класса. Увы, вы не помните, что именно делают эти 500 строк кода! К счастью, вы сохраняетесь в силу того, что параметр был скопирован перед использованием:
class Foo
{
public:
void bar( const char *where = NULL)
{
// Hooray! I only have to change 1 line here!
const char *destination = where? where : m_MyHomeDir.c_str();
// The actual implementation that in the real world may take 500
// lines of code with 20 references to the variable destination
}
private:
std::string m_MyHomeDir;
};
Я думаю, что это потому, что автор кода написал декларацию переменной в первой версии baz()
, а затем он реорганизовал код, который переместил код в цикле for в функцию foo()
, а автор ошибочно не удалил переменную. Переменная - это чистые отходы. Надеюсь это поможет!
Я не знаю, кто эти "некоторые люди" (я никогда не слышал об этом требовании), но единственная законная причина, о которой я могу думать, заключается в том, что он немного помогает в отладке: если отладчик останавливает функцию в В середине вы можете увидеть значения аргументов, изначально вызываемых. Однако в большинстве случаев вы можете достичь того же самого, просто переместив один кадр вызова и посмотрев на значения выражений, переданных функции.
Если вы делаете это в C++, просто используйте:
std::for_each(ptr, ptr+10, foo);
Я знаю, это не отвечает на вопрос напрямую, но указывает на то, что это обычно не имеет значения. Если это актуально, вам, вероятно, потребуется переписать код в целом.