【问题标题】:In C++, is it bad to pass a const bool by reference?在 C++ 中,通过引用传递 const bool 是不是很糟糕?
【发布时间】:2012-08-09 13:58:59
【问题描述】:

在实际环境中,使用 gcc 或 MS Visual Studio,通过 const 引用传递大小相同或小于 int 的值类型是否不好?

即写这样的函数是不是很糟糕:

void f(const bool& b);

void f(const char& c);

而不是:

void f(bool b);

void f(char c);

我问的原因是我看不到在这些情况下传递引用的好处,但也许我遗漏了一些东西。

【问题讨论】:

  • 正如大多数人所说,这没有任何意义,因为按值传递这些可能会更快。但是,请记住,在这些微小的优化之前编写干净的代码,有时您可能只是有几个非常相似的函数,它们通过 const 引用获取参数,然后希望 boolchar 版本看起来一致。很小的一点,但也许值得考虑,所以你不会让人们看着它思考“为什么这个不同?”

标签: c++ visual-studio gcc


【解决方案1】:

我认为传递内置类型 by value 而不是 const reference 更好,因为它实际上更快。如果通过引用传递,您需要创建一个引用(即获取一个地址),然后在使用变量时取消引用。在大多数情况下,无论如何它都会被编译器优化

【讨论】:

  • 只有函数内联才能优化。您是否考虑内联函数大多数情况是另一个问题。
【解决方案2】:

抛开性能不谈,实际上在某些情况下您会得到不同的行为。

例如,传递const 引用可确保函数无法更改引用变量的值,但另一个线程可能会这样做。如果你通过引用传递(即使是const),你会看到这些变化,如果你通过值传递,你不会。

此外,接口的定义限制了您可以对函数内的变量执行的操作。考虑这个例子:

int foo(int a) {
    a = 5; // valid
}

int bar(const int& a) {
    a = 5; // compiler-error
}

如果通过引用传递,并且想修改变量的值以供本地使用,则需要多做一份。如果你按值传递,你已经有一个副本。

【讨论】:

  • 请注意,您不需要多个线程来更改引用的变量。你可以有(例如)bool b(false); void f(const bool& a) {assert(!a); b = true; assert(a);} int main(){f(b);}.
  • +1 用于提及不同地方的参数可能发生的变化(通过其他参考资料)。这也意味着由于可能的混叠问题,将不会执行一些优化。
【解决方案3】:

虽然理论上这不是一个好主意,因为引用通常是使用指针实现的。但是,每个合理的编译器都应该足够聪明,能够识别基本类型的按常量引用和按值之间的语义差异。

如果您有某种模板化接口必须适用于复杂类型和基本类型并且您不希望过多的专业化开销(最简单的示例:std::vector),您通常别无选择。但如果您有选择,那么按值传递基本类型应该是首选。

【讨论】:

    【解决方案4】:

    一个原因是您想向其他程序员传达该值是恒定的,尽管const bool 就足够了,但在某些情况下可能会更清楚。

    【讨论】:

    • 按值传递更清楚地表明该函数不会修改调用者的值。
    • 通过 const-reference 传递并不表示源是恒定的,只是它不会被函数修改(参见 Björn 的回答:函数外的代码仍然可以更改值) .此外,const bool 作为参数根本不传达任何信息,因为在函数声明中,顶部的 cv 限定符被删除(即 void f( bool );void f( const bool ) 是完全相同的函数声明。
    【解决方案5】:

    它可能有点糟糕,或者根本没有效果(取决于原始值的存储位置、优化器的好坏以及它决定如何处理您的代码)。

    该标准没有规定如何实现引用,但实际上编译器使用指针来实现引用。因此,在一般情况下,bool& 将使用bool* 实现,这意味着要访问bool,您每次都需要一个额外的指针取消引用。由于bool 不比指针大,因此不会减少内存占用或减少字节复制来弥补这个缺点。

    因此,公认的做法是将原语作为值传递,因为它更有效。当然,尽管传递诸如引用之类的东西并不会真正破坏任何东西,除非您在循环内访问该值,否则可能甚至不会产生任何可测量的差异。

    【讨论】:

    • 当你写“由于 bool 不比指针大,因此不会减少内存占用或减少字节复制来抵消这个缺点。”,实际上是 bool 比指针占用的空间更少取决于您是否将多个布尔值作为参数传递,导致实际上通过引用传递使用更多的内存,或者布尔值与函数的参数占用相同的空间?
    • 您可能会发现通过引用传递的原始类型(即bool const&)的一种情况是在模板实例化中。除非您明确专门针对所有原始类型,否则原始类型和更复杂的类型将使用相同的签名。
    • @BlueTrin:占用多少空间取决于架构中sizeof(bool)sizeof(bool*) 的值。传递每个参数的倍数不会改变图片。
    【解决方案6】:

    这真的没关系,按值传递会使代码更简洁,因此被认为是好的做法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-26
      • 2010-12-09
      • 2011-09-20
      • 2011-10-06
      • 2018-01-20
      • 1970-01-01
      • 2022-01-24
      • 2010-12-16
      相关资源
      最近更新 更多