我总是搞砸了怎么用const int*
,const int * const
和int const *
正确的.是否有一套规则来定义您能做什么和不能做什么?
我想知道在任务,传递到职能等方面所做的所有事情和所有不应做的事情.
简短的例子:
#include <iostream>
int main()
{
int n;
[&](){n = 10;}(); // OK
[=]() mutable {n = 20;}(); // OK
// [=](){n = 10;}(); // Error: a by-value capture cannot be modified in a non-mutable lambda
std::cout << n << "\n"; // "10"
}
Run Code Online (Sandbox Code Playgroud)
问题:为什么我们需要mutable
关键字?它与传统参数传递给命名函数有很大不同.背后的理由是什么?
我的印象是,按值捕获的整个点是允许用户更改临时值 - 否则我几乎总是更好地使用按引用捕获,不是吗?
有什么启示吗?
(顺便说一句,我使用的是MSVC2010.这应该是标准的AFAIK)
int main( const int argc , const char[] const argv)
Run Code Online (Sandbox Code Playgroud)
正如有效的C++第3项规定"尽可能使用const",我开始思考"为什么不制作这些'常数'参数const
"?
是否存在argc
在程序中修改值的任何情况?
当我遇到计算立方体体积的函数时,我正在阅读我的C++书籍(Deitel).代码如下:
double cube (const double side){
return side * side * side;
}
Run Code Online (Sandbox Code Playgroud)
使用"const"限定符的解释是这样的:"const限定应该用于强制执行最小特权原则,告诉编译器函数不修改变量端".
我的问题:这里不是使用"const"冗余/不必要的,因为变量是通过值传递的,所以函数无论如何都不能修改它?
经过大量的谷歌搜索后,我发现了很多关于标记函数及其参数的内容const
,但没有关于标记变量的指南const
.
这是一个非常简单的例子:
#include <string>
#include <iostream>
void example(const std::string& x) {
size_t length = x.length();
for (size_t i = 0; i < length; ++i) {
std::cout << x.at(i) << std::endl;
}
}
int main() {
example("hello");
}
Run Code Online (Sandbox Code Playgroud)
为什么不做
size_t length = x.length();
Run Code Online (Sandbox Code Playgroud)
const喜欢
const size_t length = x.length();
Run Code Online (Sandbox Code Playgroud)
按照惯例?
我知道这么小的一个简单的例子确实没有给这个带来任何巨大的好处,但它似乎对于一个更大的代码库有帮助,你可能会意外地改变你不应该变异的变量.
尽管有这样的好处,但我并没有真正看到它使用那么多(在我见过的C++代码库中)或者提到的几乎和函数及其参数一样多const
.
除了必须输入5个额外字符外,还有一些缺点吗?我在这个话题上找不到太多东西,如果这是一个有这么多争议的问题,我不想在脚下射击.
我知道关于const正确性的问题很少,其中声明函数的声明及其定义不需要同意值参数.这是因为值参数的常量仅在函数内部很重要.这可以:
// header
int func(int i);
// cpp
int func(const int i) {
return i;
}
Run Code Online (Sandbox Code Playgroud)
这样做真的是最好的做法吗?因为我从未见过有人这样做过.我已经在其他地方看过这个引用(不确定来源),这已被讨论过:
"事实上,对于编译器,无论是否在值参数前面包含此const,函数签名都是相同的."
"避免在函数声明中使用const值传递参数.如果不修改参数const,则仍然将参数const置于同一函数的定义中."
第二段说不要将const放在声明中.我假设这是因为值参数的常量作为接口定义的一部分是没有意义的.这是一个实现细节.
根据这个建议,是否也建议指针参数的指针值?(它对参考参数没有意义,因为您无法重新分配参考.)
// header
int func1(int* i);
int func2(int* i);
// cpp
int func1(int* i) {
int x = 0;
*i = 3; // compiles without error
i = &x; // compiles without error
return *i;
}
int func2(int* const i) {
int x = 0;
*i = 3; // compiles without error
i = &x; // compile error
return *i; …
Run Code Online (Sandbox Code Playgroud) 我的同事是0 2上的问题,他一直激励着(1,2),所以我想我应该给他一个机会,迎头赶上.
我们最近的分歧是关于将"const"放在声明上的样式问题.
他认为它应该在类型前面,或者在指针之后.原因在于,这是其他人通常所做的事情,其他风格可能会让人感到困惑.因此,指向常量int的指针和指向int的常量指针将分别为:
const int *i;
int * const i;
Run Code Online (Sandbox Code Playgroud)
但是,无论如何我很困惑.我需要的是一致的,易于理解的规则,我可以做的"常量"意义上的唯一方法是,它去后,它被修改的事情.有一个例外允许它在最终类型前面,但这是一个例外,所以如果我不使用它,它会更容易.
因此,指向常量int的指针和指向int的常量指针将分别为:
int const * i;
int * const i;
Run Code Online (Sandbox Code Playgroud)
作为一个额外的好处,以这种方式做事使得更深层次的间接更容易理解.例如,指向int的常量指针的指针显然是:
int * const * i;
Run Code Online (Sandbox Code Playgroud)
我的论点是,如果有人只是按照自己的方式学习,他们就可以轻松搞清楚上面的内容.
这里的最终问题是他认为将int放在int之后是如此难以言喻的丑陋,对可读性有害,以至于它应该在样式指南中被禁止.当然,我认为如果指南应该建议按照我的方式做,但无论哪种方式,我们都不应该禁止一种方法.
编辑: 我已经得到了很多好的答案,但没有一个真正直接解决我的最后一段("最终问题").很多人都争论一致性,但在这种情况下是如此理想,禁止其他方式这样做是一个好主意,而不是仅仅劝阻它?
在以下C++函数中:
void MyFunction(int age, House &purchased_house)
{
...
}
void MyFunction(const int age, House &purchased_house)
{
...
}
Run Code Online (Sandbox Code Playgroud)
哪个更好?
在两者中,'年龄'都是按价值传递的.我想知道'const'关键字是否有必要:对我来说似乎是多余的,但也很有用(作为额外的指示,变量不会改变).
有没有人对上述哪个(如果有的话)更好有任何意见?
我最近与另一位C++开发人员就以下用途进行了交流const
:
void Foo(const int bar);
Run Code Online (Sandbox Code Playgroud)
他认为const
以这种方式使用是很好的做法.
我认为它对函数的调用者没有任何作用(因为参数的副本将被传递,因此对于覆盖没有额外的安全保证).此外,这样做可以防止实现者Foo
修改其参数的私有副本.因此,它既要求又要宣传实施细节.
不是世界末日,但肯定不是值得推荐的良好做法.
我很好奇别人对这个问题的看法.
好吧,我没有意识到参数的常数没有考虑到函数的签名.因此,可以const
在实现(.cpp)中标记参数,而不是在标题(.h)中标记- 并且编译器就可以了.既然如此,我想政策应该与制作局部变量const相同.
人们可以提出这样的论点:在标题和源文件中具有不同的看起来签名会使其他人感到困惑(因为它会使我感到困惑).虽然我试着用我写的任何内容来遵循最小惊讶原则,但我认为期望开发人员认为这是合法且有用的是合理的.
学习C++时,学习函数概念的第一个函数之一就是
int add(int a, int b)
{
return a+b;
}
Run Code Online (Sandbox Code Playgroud)
现在我想知道:我应该在const
这里使用-keyword,或者更确切地说不是,因此
int add(const int a, const int b)
{
return a+b;
}
Run Code Online (Sandbox Code Playgroud)
但那会有意义吗?它会加速我的程序,做一些其他重要的事情,或只是增加混乱?