C++:常量正确性和指针参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8808167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++: Const correctness and pointer arguments
提问by Ben
I understand that a const pointer can be declared a couple ways:
我知道可以通过几种方式声明 const 指针:
const int * intPtr1; // Declares a pointer that cannot be changed.
int * const intPtr2; // Declares a pointer whose contents cannot be changed.
// EDIT: THE ABOVE CLAIMS ARE INCORRECT, PLEASE READ THE ANSWERS.
But what about the same principles within the context of function arguments?
但是在函数参数的上下文中相同的原则呢?
I would assume that the following is redundant:
我认为以下内容是多余的:
void someFunc1(const int * arg);
void someFunc2(int * arg);
Since someFunc 1 and 2 do a pass-by-value for the pointer itself, its impossible for someFunc1 to change the value of the original pointer, in a given call to the function. To illustrate:
由于 someFunc 1 和 2 对指针本身进行值传递,因此 someFunc1 不可能在给定的函数调用中更改原始指针的值。为了显示:
int i = 5;
int * iPtr = &i;
someFunc1(iPtr); // The value of iPtr is copied in and thus cannot be changed by someFunc1.
If these are true, then there is no point in ever declaring a function with a 'const int * ptr' type arg, correct?
如果这些都是真的,那么声明一个带有'const int * ptr'类型arg的函数就没有意义了,对吗?
回答by Mike Seymour
You have it backwards:
你有它倒退:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
The following const
is indeed unnecessary, and there's no reason to put it in a function declaration:
以下const
确实是不必要的,并且没有理由将其放在函数声明中:
void someFunc1(int * const arg);
However, you might want to put it in the function implementation, for the same reason that you might want to declare a local variable (or anything else) const
- the implementation may be easier to follow when you know that certain things won't change. You can do that whether or not it's declared const
in any other declarations of the function.
但是,您可能希望将它放在函数实现中,原因与您可能希望声明局部变量(或其他任何东西)的原因相同const
- 当您知道某些事情不会改变时,实现可能更容易遵循。无论它是否const
在函数的任何其他声明中声明,您都可以这样做。
回答by havexz
Well it is not meant for the caller but for the code inside the someFunc1
. So that any code inside someFunc1
wont accidentally change it. like
好吧,它不是针对调用者,而是针对someFunc1
. 这样里面的任何代码都someFunc1
不会意外更改它。喜欢
void someFunc1(int *arg) {
int i = 9;
arg = &i; // here is the issue
int j = *arg;
}
Lets do some case study:
让我们做一些案例研究:
1) Just making the pointed value const
1)只是使指向值const
void someFunc1(const int * arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
}
2) Just making the pointer const
2)只是使指针const
void someFunc1(int * const arg) {
int i = 9;
arg = &i; // <- compiler error as pointer is const
}
3) Right way to use const if variables involved can be const:
3)如果涉及的变量可以是const,则使用const的正确方法:
void someFunc1(const int * const arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
arg = &i; // <- compiler error as pointer is const
}
This should clear all doubts. So I already mentioned it is meant for the function code and not for the caller and you should use the most restrictive of the 3 cases i mentioned above.
这应该消除所有疑虑。所以我已经提到它是针对函数代码而不是针对调用者的,您应该使用我上面提到的 3 种情况中最严格的一种。
EDIT:
编辑:
- Even in declarations of functions its a good practice to declare
const
. This will not only increase readability but also the caller will be aware of the contract and has more confidence regarding immutability of arguments. (This is required bcoz you generally share your header files so caller might not have your implementation c/cpp file) - Even compiler can point out better if both declaration and definitions are in sync.
- 即使在函数声明中,声明
const
. 这不仅会增加可读性,而且调用者会知道合约并且对参数的不变性更有信心。(这是必需的,因为您通常会共享头文件,因此调用者可能没有您的实现 c/cpp 文件) - 如果声明和定义同步,甚至编译器也可以更好地指出。
回答by mattjgalloway
You've got your logic the wrong way round. You should read the type backwards, so const int *
is a pointer to a const int
and int * const
is a const
pointer to an int.
你的逻辑是错误的。您应该向后阅读类型,const int *
指向 a 的指针const int
和指向 intint * const
的const
指针也是如此。
Example:
例子:
void foo() {
int a = 0;
int b = 0;
int * const ptrA = &a;
*ptrA = 1;
ptrA = &b; ///< Error
const int * ptrB = &a;
*ptrB = 1; ///< Error
ptrB = &b;
const int * const ptrC = &a;
*ptrC = 1; ///< Error
ptrC = &a; ///< Error
}
To elaborate and show why you would want your function parameter to be a const int *
you might want to indicate to the caller that they must pass in an int
because you as a function want to change the value. Consider this code for instance:
为了详细说明并说明为什么您希望函数参数为 a,const int *
您可能希望向调用者表明他们必须传入 an,int
因为您作为函数想要更改该值。例如,考虑以下代码:
void someFunc1(const int * arg) {
// Can't change *arg in here
}
void someFunc2(int * arg) {
*arg = 5;
}
void foo() {
int a = 0;
someFunc1(&a);
someFunc2(&a);
const int b = 0;
someFunc1(&b);
someFunc2(&b); ///< *** Error here. Must pass in an int not a const int.
}
回答by Puppy
Yes, you are correct (ignoring the fact that you got them the wrong way around)- there is no sense in taking non-reference const
parameters. In addition, there is no sense in returning non-reference const
values.
是的,您是对的(忽略了您以错误的方式获取它们的事实)-采用非参考const
参数是没有意义的。此外,返回非引用const
值也没有任何意义。
回答by Grizzly
You have it the wrong way:
你的方式不对:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
Generally speaking its easier to reason about constness when writting that expression slightly different: const int*
is the same type as int const *
. In that notation the rules are much clearer, const
always applies to the type preceding it, therefore:
一般来说,在编写稍微不同的表达式时,更容易推理常量性:const int*
与int const *
. 在这种表示法中,规则更加清晰,const
始终适用于它前面的类型,因此:
int const * intPtr1; // Declares a pointer to const int.
int * const intPtr2; // Declares a const pointer to int.
int const * * const * complexPtr; // A pointer to const pointer to pointer to const int
When the type is written with a leading const
, the const
is handled as if it was written after the first type, so const T*
becomes T const *
.
当使用前导写入类型时const
, 将const
被处理为好像它是在第一个类型之后编写的,因此const T*
变为T const *
。
void someFunc2(int * arg);
Is therefore not redundant, since someFunc2
may change the contents of arg
, while someFunc1
may not. void someFunc3(int * const arg);
would be redundant (and ambigous) though
因此不是多余的,因为someFunc2
可能会更改 的内容arg
,而someFunc1
可能不会。void someFunc3(int * const arg);
虽然将是多余的(和模棱两可的)