11

我应该注意const使用原始类型的修饰符吗?哪一个在语法上更正确,为什么?

第一个版本:

float Foo::bar(float a, float b)
{
    return (a + b) / 2.0f;
}

第二个版本:

const float Foo::bar(const float a, const float b)
{
    return (a + b) / 2.0f;
}

第三版:

float Foo::bar(const float a, const float b)
{
    return (a + b) / 2.0f;
}

我知道原始类型的变量在传递给某个方法时会被复制,但是哪种方法更清楚?

4

5 回答 5

20

我会说第三个版本是最“正确”的。

您告诉编译器参数是const,这是正确的,因为您没有修改它们。这可以帮助编译器优化传递参数以及计算。

并且返回类型不是const因为调用者可能想要修改返回值。如果调用者不想修改返回值,则由调用者将其分配给const变量。

我也会添加const到函数声明中,因为该函数不会修改对象中的任何内容:

float Foo::bar(const float a, const float b) const
于 2013-04-16T09:49:41.590 回答
4

首先,您提供的所有定义在语法上都是正确的。如果它们编译,那么它们在语法上是正确的。

const参数限定符只有一个目的:防止函数体修改限定const参数。

在您的示例代码的特定情况下,该方法Foo::bar不会修改参数,因此使用const限定符没有任何效果。

但是,您可能希望const在所有情况下都使用默认值,并且仅在您希望允许修改的情况下将其删除。因此,将其应用于参数Foo::bar是一个好主意。我认为这是一种很好的做法,尽管我承认我很少使用它,因为它会产生一点噪音,这可能会降低可读性。

另一件需要考虑的事情是,对于原始类型,或者更准确地说,不是指针或不包含指针的类型,修改按值传递的参数(即不是通过引用)不会有任何副作用:这些类型的参数确实起作用作为初始化的局部变量(这可能很方便,但也可能令人困惑)。对于指针,任何对指向数据的修改都会泄露给外界。这是在指针和类型的指向部分const使用限定符的另一个很好的理由。

总而言之,const尽可能多地使用限定符将有助于使代码不易出错,还可以帮助编译器优化生成的程序。

但是,如果这些类型描述了适合 CPU 寄存器的值(通常是这种情况),则使用这些类型的引用不应产生任何重大变化,

因此,该方法的所有三个版本都应该归结为相同的生成汇编代码。

在原始返回类型的特定情况下,这无关紧要。返回值可以来回转换为const合格的。

其他人也提到了const限定符对函数本身的兴趣。虽然超出了最初的问题范围,但我还要说,在可能的情况下(例如 for Foo::bar)将函数限定为 确实更好const

于 2013-04-16T10:17:11.780 回答
1

第 2 版和第 3 版完全没有区别。选择一个最短的类型:)

1号和3号有一点区别。如果您害怕不小心修改ab在函数内部,您可能更喜欢第 3 个。

于 2013-04-16T09:50:26.600 回答
1

简短的回答:没关系。

长答案:因为您按值传递两个参数并按值返回参数。其中任何一个都很好,但您会更常见地看到第一个版本。

如果您通过引用传递(正如其他人所建议的那样),那么它确实很重要,您应该使用 const-reference。但是,通过引用传递原始类型并没有真正给您带来任何优势或意义(如果它是 const 引用)。这样做的原因是,与通过引用传递基本类型相比,按值传递基本类型不会产生任何开销。

于 2013-04-16T09:52:18.577 回答
1

我要说的是,对于原语,实际复制它们可能会更有效。当你传递一个引用时,编译器仍然必须传递堆栈上的字节,然后必须取消引用地址以获取内容。

此外,按值传递克服了与传递的内存有关的任何可能的并发性/波动性问题。

这是“不要尝试在这里优化”的情况。

通过 const 返回是风格。我通常不这样做,其他人更喜欢以防万一有人用返回的值做某事。接下来,您会发现人们通过 r 值引用返回它们...

我通常会选择你的第一个选项。另一种选择是按值传递(不必使用 const)并按 const 值返回。

于 2013-04-16T09:53:30.630 回答