带有基本类型的C ++ const修饰符

时间:2013-04-16 09:45:59

标签: c++

我应该注意使用原始类型的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;
}

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

5 个答案:

答案 0 :(得分:14)

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

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

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

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

float Foo::bar(const float a, const float b) const

答案 1 :(得分:2)

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

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

在示例代码的特定情况下,方法Foo::bar不会修改参数,因此使用const限定符不会产生任何影响。

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

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

总而言之,尽可能使用const限定符将有助于减少代码的错误,并且还可以帮助编译器优化生成的程序。

如果这些类型描述适合CPU寄存器的值(通常是这种情况),则使用这些类型的引用不应进行任何重大更改,

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

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

其他人也提到了const限定符对函数本身的兴趣。虽然在原始问题范围之外,我还会说尽可能更好(例如Foo::bar)将函数限定为const

答案 2 :(得分:1)

第2版和第3版之间没有任何区别。选择一个最短的类型:)

第1和第3之间有一点差别。如果你害怕在函数内部意外修改ab,你可能更喜欢第3个。

答案 3 :(得分:1)

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

此外,按值传递可以克服任何可能的并发/易变性问题,这些问题与传递的内容有关。

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

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

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

答案 4 :(得分:0)

简短回答:没关系。

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

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