C++ C++;:常量正确性和指针参数

C++ C++;:常量正确性和指针参数,c++,function,pointers,constants,C++,Function,Pointers,Constants,我知道常量指针可以通过以下几种方式声明: 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. 但是,在函数参数的上下文中,相同的

我知道常量指针可以通过以下几种方式声明:

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对指针本身执行传递值,因此在给定的函数调用中,someFunc 1不可能更改原始指针的值。举例说明:

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
参数是没有意义的。此外,返回非引用的
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
}
void someFunc1(常量int*arg){
int i=9;

*arg=i;//您的逻辑搞错了。您应该向后读取类型,因此
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 * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
以下
const
确实是不必要的,没有理由将其放在函数声明中:


但是,您可能希望将其放在函数实现中,原因与您可能希望声明局部变量(或其他任何内容)的原因相同
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);
将是多余的(和模糊的),尽管您的声明是错误的。“const-int*”是指向不可更改的int的可变指针。“int*const"是一个指向可变整数的不可更改指针。编辑该问题是为了让喜欢触发的Google用户不会得到错误信息。我留下了错误,以便答案仍然有上下文。非引用
const
返回值甚至有害。@Xeo:请详细说明一下,好吗?我根本不知道它们有任何影响!@ruakh:看,这是一个相当小的问题。@ruakh:移动语义就是其中之一。
T const&&
不能从中移动,即使你知道它是一个临时的,很快就会被销毁。@ruakh:那篇文章是十多年前写的,所以是的,在移动语义建立之前很久。但这并不能解释为什么你要写
void someFunc1(常量int*arg);
。请注意,将
someFunc1
预声明为
void someFunc1(int*arg);
仍允许您将其定义为
void someFunc1(int*const arg){…}
如果需要,参数变量本身的
常数不会影响实际的函数签名。@ruakh请检查更新后的ans。这应该是您的问题。对不起,不,您的更新后的答案仍然没有回答问题。(有关正确答案,请参阅上面Mike Seymour的答案。)“但是,您可能希望将其放在函数实现中,原因与您可能希望声明一个局部变量(或任何其他)const”=“我已经提到过它是用于函数代码而不是用于调用方的"…无论如何,这一点很清楚,这就是底线…我想我只是对回答这个问题的答案有一种奇怪的偏好!现在我看起来像个傻瓜…感谢你的简明解释,并确认其中一个定义中确实存在不必要的常量。
const int*intPtr1
int-const*intPtr1;
?@yes123:没有区别。
const
限定前面的东西,除非它在开头,在这种情况下它限定第一件事。所以在这两种情况下,它限定
int
,而不是指针。
int-const
将限定指针。@MikeSeymour:哇,这太清楚了,我想知道有什么问题问这个?(我发现这个问题可以通过你的评论来解决。)常见技巧:从右到左读取任何c类声明:
int-const*intPtr1
-->
intPtr1
是指向常量(只读)整数的指针
void someFunc1(int * const arg);
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
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
void someFunc2(int * arg);