带有基本类型的c++ const修饰符
C++ const modifier with primitive types
我应该注意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;
}
我知道原始类型的变量在传递给某些方法时被复制,但哪种方式更清楚?
我认为第三个版本是最"正确"的。
你告诉编译器参数是const
,这是正确的,因为你没有修改它们。这可以帮助编译器优化参数的传递和计算。
返回类型不是const
,因为调用者可能想要修改返回值。如果调用者不想修改返回值,则由调用者将其分配给const
变量。
我还会将const
添加到函数声明中,因为该函数不会修改对象中的任何内容:
float Foo::bar(const float a, const float b) const
由于该函数不访问对象的任何成员,那么我也将其设为static
。
首先,您提供的所有定义语法正确。如果它们可以编译,那么它们的语法是正确的。
形参上的const
限定符只有一个目的:防止函数体修改const
限定实参。
在您的示例代码的特定情况下,Foo::bar
方法不修改参数,因此使用const
限定符没有任何影响。
但是,您可能希望在所有情况下默认使用const
,并且仅在希望允许修改的情况下删除它。因此,将它应用于Foo::bar
的参数是一个好主意。我认为这是一个很好的实践,尽管我应该承认我很少使用它,因为它会产生一些噪音,这可能会降低可读性。
另一件需要考虑的事情是,对于基本类型,或者更准确地说,不是指针或不包含指针的类型,修改按值传递的实参(即:(不是通过引用)不会有任何副作用:这些类型的参数实际上充当初始化的局部变量(这可能很方便,但也可能令人困惑)。对于指针,对指向数据的任何修改都将泄露给外部世界。这是在指针和类型的指向部分同时使用const
限定符的另一个很好的理由。
总而言之,尽可能多地使用const
限定符将有助于使代码更不容易出错,还可以帮助编译器优化生成的程序。
使用这些类型的引用不应该有任何明显的改变,如果这些类型描述的值适合CPU寄存器(通常是这种情况),
因此,该方法的所有三个版本都应该归结为生成的相同汇编代码。
在基本返回类型的特殊情况下,这无关紧要。返回值可以来回转换为符合const
标准的值。
其他人也提到了const
限定符对函数本身的兴趣。虽然超出了原来的问题范围,但我也会说,如果可能的话(如Foo::bar
),将函数限定为const
确实更好。
第二版和第三版之间没有任何区别。选择输入时间最短的一个:)
第一个和第三个有一点不同。如果您担心不小心修改函数中的a
和b
,您可能更喜欢第三种方法。
简短的回答:没关系。
长答:因为你是按值传递两个实参并按值返回实参。这两种都可以,但您更经常看到的是第一个版本。
如果你通过引用传递(就像其他人建议的那样),那么它确实很重要,你应该使用const-reference。然而,通过引用传递基本类型并没有真正给您带来任何好处或意义(如果它是const引用)。这样做的原因是,与按引用传递基本类型相比,按值传递基本类型不会产生任何开销。
我要说的是,对于原语来说,实际复制它们可能更有效。当你传递一个引用时,编译器仍然必须在堆栈上传递字节,然后必须对地址解引用以获得内容。
此外,按值传递克服了任何可能的并发性/波动性问题,这些问题与正在传递的内存有关。
这是一个"不要试图在这里优化"的例子。
按const返回是一种风格。我通常不这样做,其他人更喜欢这样做,以防有人要对返回值做一些事情。接下来你会发现人们通过r值引用返回它们…
我通常会选择你的第一个选项。另一种方法是按值传递(不需要使用const)并按const值返回。