Стиль C / C ++ - изменение аргументов функции

0

Всем известно, что аргументы функции 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++);
  }
}

Похоже, что второй способ легче читать, поскольку он является одним менее переменным.

  • 1
    Я так и не понял, почему люди так делают. Может быть, те, кто пришел из C ++, привыкли к риску случайной передачи и изменения ссылки ... ну, не очень хорошо.
  • 0
    Может быть, чтобы исходные значения аргументов функции можно было легко увидеть в любых файлах дампа ядра? Я действительно не знаю.
Показать ещё 7 комментариев
Теги:
pass-by-value
coding-style

6 ответов

3
Лучший ответ

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

Представить:

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

Его попытка взять автора два в то время, чтобы понять, что новый код никогда не будет работать.

2

Они делают это, потому что исходное значение полезно при отладке.

1

Это версия бедного человека о разделении интерфейса от реализации.

Предположим, вы написали этот код год назад:

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;
};
1

Я думаю, что это потому, что автор кода написал декларацию переменной в первой версии baz(), а затем он реорганизовал код, который переместил код в цикле for в функцию foo(), а автор ошибочно не удалил переменную. Переменная - это чистые отходы. Надеюсь это поможет!

0

Я не знаю, кто эти "некоторые люди" (я никогда не слышал об этом требовании), но единственная законная причина, о которой я могу думать, заключается в том, что он немного помогает в отладке: если отладчик останавливает функцию в В середине вы можете увидеть значения аргументов, изначально вызываемых. Однако в большинстве случаев вы можете достичь того же самого, просто переместив один кадр вызова и посмотрев на значения выражений, переданных функции.

0

Если вы делаете это в C++, просто используйте:

std::for_each(ptr, ptr+10, foo);

Я знаю, это не отвечает на вопрос напрямую, но указывает на то, что это обычно не имеет значения. Если это актуально, вам, вероятно, потребуется переписать код в целом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню