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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:08:31  来源:igfitidea点击:

C++: Const correctness and pointer arguments

c++functionpointersconst

提问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 constis 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 constin 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 someFunc1wont 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 intand int * constis a constpointer to an int.

你的逻辑是错误的。您应该向后阅读类型,const int *指向 a 的指针const int和指向 intint * constconst指针也是如此。

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 intbecause 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 constparameters. In addition, there is no sense in returning non-reference constvalues.

是的,您是对的(忽略了您以错误的方式获取它们的事实)-采用非参考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, constalways 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 constis 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 someFunc2may change the contents of arg, while someFunc1may not. void someFunc3(int * const arg);would be redundant (and ambigous) though

因此不是多余的,因为someFunc2可能会更改 的内容arg,而someFunc1可能不会。void someFunc3(int * const arg);虽然将是多余的(和模棱两可的)