在C和C ++中,可以在定义函数时声明参数const
// without const
void foo(int i)
{
// implementation of foo()
}
// with const
// const communicates the fact that the implementation of foo() does not modify parameter i
void foo(const int i)
{
// implementation of foo()
}
但是,从调用者的角度来看,两个版本是相同的(具有相同的签名)。复制传递到foo()
的参数值。 foo()
可能会更改该副本,而不是调用方传递的值。
这很好,但是在声明 const
时也可以使用foo()
:
void foo(int i); // normal way to declare foo()
void foo(const int i); // unusual way to declare foo() - const here has no meaning
为什么在声明const
时C和C ++标准允许foo()
,即使在这样的声明中它没有意义?为什么要这样const
这样荒谬的使用?
答案 0 :(得分:1)
const
是类型限定符:https://en.cppreference.com/w/cpp/language/cv
因此,它们可以作为语法本身的一部分添加到类型中。我想他们不想以不同的方式指定参数和变量。 (这可能会使实现起来更容易一些?)
然后的问题是,当他们引用参数本身时,他们不参与签名(例如,当他们引用参数所指向的内存时,它们是签名的一部分)
clang-tidy的规则是删除多余的const
:https://clang.llvm.org/extra/clang-tidy/checks/readability-avoid-const-params-in-decls.html
答案 1 :(得分:0)
没有理由在非定义声明中禁止在函数参数上使用限定符,并允许源代码在定义和任何非定义声明中保留相同的声明。
在定义中,const
和其他限定词具有其正常的作用,如:
int foo(const int x)
{
x = 3; // Not permitted.
}
假设我们不希望失去这种行为,在定义中允许使用限定符,而在不是声明的声明中禁止使用限定符会使标准不必要地复杂化。另外,这意味着复制定义以将其作为非定义声明粘贴到其他地方的人们将不得不进行其他编辑,并且任何旨在从源文件收集外部定义以创建包含非定义声明的头文件的软件都将具有进行额外的解析和操作以剥离限定符(但仅限顶级限定符,而不是类型内部的限定符,例如int * const p
)。
通常,C和C ++语言不会禁止“无用”的事情,例如添加一个常数零(这可能是预处理器宏的组合产生的,对于某些选择的构建选项,某些表达式恰好等于零) ,孤立的空语句等。除非它们助长了人类犯错误的倾向,否则这些事情将不重要。例如,如果加零总是由于错误而发生(因此,它从未因上述错误而发生),则禁止它具有价值。但是,如果禁止某物没有任何价值,那么加大力度禁止它就是浪费。
答案 2 :(得分:-2)
首先,函数参数中的const不是没有意义的。考虑以下代码:
void foo(int i)
{
i++;
std::cout << i << "\n";
}
如果添加const则不可能。如果通过值传递,则由值传递的参数是函数的局部变量。声明为const就是告诉编译器变量i在其生命周期内无法更改其值。
仍然没有太大用处吗?在C中,也许。在C ++中,这还意味着您不能调用按值传递的类型类的非const方法。假设参数可以是类类型的对象,并且是存储在函数外部的某些对象的接口。然后,您声明函数必须将该对象保留为“不可变的”确实有意义。
Const不参与这种特殊情况以形成函数签名,因此在相同范围内或在名称查找期间遇到这两个变体会导致程序格式错误。在其他情况下,它可能会定义参数值类别之间的差异。