【问题标题】:C/C++ style -- modifying function arguments [closed]C/C++ 风格——修改函数参数
【发布时间】:2013-12-13 19:47:00
【问题描述】:

每个人都知道 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++);
  }
}

似乎第二种方式更容易阅读,因为它少了一个变量。

【问题讨论】:

  • 我也不明白为什么人们会这样做。也许那些来自 C++ 的人已经习惯了意外传递和修改引用的风险......呃,不太好。
  • 也许可以在任何核心转储文件中轻松看到函数参数的原始值?我真的不知道。
  • 这些人是谁?我同意你的看法。
  • 这里也一样...那我猜不是每个人都...
  • 我曾经看过一门“学习 C”课程的笔记,它教授了一种高度公式化的方法,其中包括这种东西。对我来说感觉像是在浪费空间。

标签: c++ c coding-style pass-by-value


【解决方案1】:

唯一的理由是对于更大的函数,有人可能会在函数底部添加新功能,而没有意识到参数已被修改或之前无效。

想象一下:

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】:

    他们这样做是因为原始值在调试时很有用。

    【讨论】:

      【解决方案3】:

      我想是因为代码的作者在baz()的第一版中写了变量的声明,然后他重构了代码,将for循环中的代码移到了函数foo()中,并且作者错误地没有删除变量。变量是纯粹的浪费。希望这会有所帮助!

      【讨论】:

        【解决方案4】:

        这是接口与实现分离的穷人版本。

        假设您在一年前编写了这段代码:

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

        现在,一年后,您想让参数 where 可选,默认为类的成员变量。唉,你不记得那 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;
        };
        

        【讨论】:

          【解决方案5】:

          如果你是用 C++ 做的,只需使用:

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

          我知道,这并不能直接回答问题,但确实指出了它通常应该是无关紧要的事实。如果它是相关的,你可能需要重写代码。

          【讨论】:

            【解决方案6】:

            我不清楚这些“某些人”是谁(我从未听说过这种需求),但我能想到的唯一正当理由是它对调试有一点帮助:如果调试器停止在中间的函数中,您可以看到最初调用它的参数值。但是在大多数情况下,您可以通过向上移动一个调用帧并查看传递给函数的表达式的值来实现相同的目的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-10-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-06-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多