C++:构造正确性和指针参数
C++: Const correctness and pointer arguments
我知道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.
但是,在函数论证的上下文中,同样的原理又如何呢?
我认为以下内容是多余的:
void someFunc1(const int * arg);
void someFunc2(int * arg);
由于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.
如果这些都是真的,那么用"const-int*ptr"类型的arg声明函数就没有意义了,对吗?
你有它向后:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
以下const
确实是不必要的,并且没有理由将其放在函数声明中:
void someFunc1(int * const arg);
然而,您可能希望将其放入函数实现中,原因与您可能希望声明局部变量(或其他任何变量)const
的原因相同——当您知道某些事情不会改变时,实现可能更容易遵循。无论它是否在函数的任何其他声明中声明为const
,都可以执行此操作。
这不是为调用者准备的,而是为someFunc1
内部的代码准备的。这样someFunc1
中的任何代码都不会意外地更改它
void someFunc1(int *arg) {
int i = 9;
arg = &i; // here is the issue
int j = *arg;
}
让我们做一些案例研究:
1) 只是使点值常量
void someFunc1(const int * arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
}
2) 只是使指针常量
void someFunc1(int * const arg) {
int i = 9;
arg = &i; // <- compiler error as pointer is 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
}
这应该消除所有疑虑。所以我已经提到了它是针对函数代码的,而不是针对调用者的,你应该使用我上面提到的3种情况中最严格的一种。
编辑:
- 即使在函数的声明中,声明
const
也是一种很好的做法。这不仅会增加可读性,而且调用者会意识到契约,并对参数的不变性更有信心。(这是必需的,因为您通常共享头文件,所以调用者可能没有您的实现c/cpp文件) - 若声明和定义同步,即使编译器也能更好地指出
您的逻辑错误。您应该向后读取类型,因此const int *
是指向const int
的指针,int * const
是指向int的const
指针
示例:
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
}
为了详细说明和显示为什么希望函数参数为const int *
,您可能需要向调用方指示它们必须传入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.
}
是的,你是对的(忽略了你把它们弄错的事实)-采用非参考const
参数是没有意义的。此外,返回非参考const
值是没有意义的。
你有错误的方式:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
一般来说,当编写稍微不同的表达式时,更容易推断常量: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
当用前导const
写入类型时,const
被处理为如同在第一个类型之后写入一样,因此const T*
变为T const *
。
void someFunc2(int * arg);
因此不是多余的,因为someFunc2
可以改变arg
的内容,而someFunc1
可以不改变。void someFunc3(int * const arg);
将是冗余的(和模糊的),尽管
- 为函数定义符号不明确的指针参数
- 构造函数 (C++) 中的 char 指针参数存在问题
- 按引用调用与按指针参数调用的差异 前递增和后递增
- 为什么具有指针参数的成员函数需要指向指针的指针?
- 通过引用函数传递指针参数是什么意思?
- 从double到double*的指针参数
- void 函数中的指针参数返回不一致的值
- 无法向上转换指针到指针参数
- 将数组动态分配到具有指针参数的函数中
- 模板函数指针参数与构造函数参数
- 使用通用函数指针参数化函数模板的简洁方法
- 如何为C++字符串分配空指针参数?
- C++带有指针参数的函数
- 指针参数的默认值
- 将常量添加到函数模板指针参数
- 如何传递unique_ptr<T>代替原始*输出*指针参数?
- 不带星号的函数指针参数
- 功能指针参数参数转换为const
- 将指针参数传递给双指针参数
- 如何调试指针参数是否通过函数修改