Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';常量指针的意义是什么?_C++_C_Pointers_Constants - Fatal编程技术网

C++ 什么';常量指针的意义是什么?

C++ 什么';常量指针的意义是什么?,c++,c,pointers,constants,C++,C,Pointers,Constants,我说的不是指向常量值的指针,而是常量指针本身 我学习C和C++,超越了最基本的东西,直到今天我才意识到指针是通过值传递给函数的,这是有意义的。 这意味着在函数中,我可以使复制的指针指向其他值,而不会影响调用方的原始指针 那么,有一个函数头的意义是什么呢 void foo(int* const ptr); 在这样一个函数中,你不能让ptr指向其他对象,因为它是常量,你不想修改它,但是像这样的函数: void foo(int* ptr); void func (int*const* ptrptr

我说的不是指向常量值的指针,而是常量指针本身

我学习C和C++,超越了最基本的东西,直到今天我才意识到指针是通过值传递给函数的,这是有意义的。 这意味着在函数中,我可以使复制的指针指向其他值,而不会影响调用方的原始指针

那么,有一个函数头的意义是什么呢

void foo(int* const ptr);
在这样一个函数中,你不能让ptr指向其他对象,因为它是常量,你不想修改它,但是像这样的函数:

void foo(int* ptr);
void func (int*const* ptrptr)

这工作也做得很好!因为指针是以任何方式复制的,即使修改了副本,调用方中的指针也不会受到影响。那么const的优点是什么呢?

你说得对,对于调用者来说,它完全没有区别。但对于函数的编写者来说,它可以是一个安全网“好吧,我需要确保我没有把这一点指向错误的东西”。不是很有用,但也不是无用的


这基本上与程序中有一个
int const the_answer=42
是一样的。

指针没有什么特别之处,你永远不希望它们是const。正如您可以使用类成员常量
int
值一样,您也可以使用常量指针,原因类似:您希望确保没有人更改所指向的内容。C++引用有点解决这个问题,但是指针行为是从C.< /P> < P>继承的。我相信这会阻止代码在函数体内递增或递减指针。

< P>传递一个const指针到函数没有意义,因为它无论如何都会被传递。这只是一般语言设计所允许的事情之一。仅仅因为它没有意义就禁止它只会使语言规范变得更大


如果你在一个函数中,那当然是另一种情况。拥有一个不能更改其指向的指针是一种使代码更清晰的断言。

我想一个优点是编译器可以在知道该指针不能更改的情况下在函数内部执行更积极的优化

它还避免了将此指针传递给接受非常量指针引用的子函数(因此可以更改指针,如
void f(int*&p)
),但我同意,在这种情况下,有用性有些有限。

我强调只使用
const
参数,因为这样可以进行更多的编译器检查:如果我不小心在函数中重新分配了参数值,编译器会咬我

我很少重用变量,创建新变量来保存新值更干净,因此基本上我所有的变量声明都是
const
(某些情况除外,例如循环变量
const
会阻止代码工作)

请注意,这仅在函数的定义中才有意义。它不属于用户看到的声明。用户不在乎我是否使用
const
作为函数内部的参数

例如:

// foo.h
int frob(int x);

请注意,参数和局部变量都是
const
。这两种方法都不是必需的,但对于更大的函数来说,这一方法多次避免了我犯错误。

顶级常量限定符在声明中被丢弃,因此问题中的声明声明声明了完全相同的函数。另一方面,在定义(实现)中,编译器将验证如果将指针标记为const,则它不会在函数体内部修改。

int iVal=10; int*const ipPtr=&iVal

与普通常量变量一样,常量指针必须在声明时初始化为值,并且其值不能更改

这意味着常量指针将始终指向相同的值。在上述情况下,ipPtr将始终指向iVal的地址。但是,由于指向的值仍然是非常量,因此可以通过取消引用指针来更改指向的值:


*ipPtr=6;//允许,因为PNPTR指向非cont int

<代码> const 是一个工具,您应该用它来追求一个非常重要的C++概念:

通过让编译器执行您的意思,在编译时而不是运行时查找bug

即使它不会改变功能,添加
const
也会在您做一些不想做的事情时生成编译器错误。想象一下以下打字错误:

void foo(int* ptr)
{
    ptr = 0;// oops, I meant *ptr = 0
}

如果使用
int*const
,这将生成一个编译器错误,因为您正在将值更改为
ptr
。一般来说,通过语法添加限制是一件好事。只是不要走得太远——你举的例子是,大多数人都不想麻烦使用
const

你的问题涉及到一个更一般的问题:函数参数应该是const吗

值参数的常量(如指针)是一个实现细节,它不构成函数声明的一部分。这意味着您的功能始终是:

void foo(T);
函数的实现者是否希望以可变方式或常量方式使用函数范围参数变量,完全取决于该函数的实现者:

// implementation 1
void foo(T const x)
{
  // I won't touch x
  T y = x;
  // ...
}

// implementation 2
void foo(T x)
{
  // l33t coding skillz
  while (*x-- = zap()) { /* ... */ }
}

因此,如果您不想或不需要修改变量,请遵循一条简单的规则,永远不要将
const
放在声明(标题)中,并将其放在定义(实现)中。

对于任何其他类型(不仅仅是指针),也可以问相同的问题:

…今天我意识到指针是通过值传递给函数的,这很有意义

(imo)作为默认设置,它真的没有意义。更合理的默认设置是作为不可重新分配的指针传递(
int*const arg
)。也就是说,我宁愿
/* Why is n const? */
const char *expand(const int n) {
    if (n == 1) return "one";
    if (n == 2) return "two";
    if (n == 3) return "three";
    return "many";
}
void func(int* const arg) {
    int* a(arg);
    ...
    *a++ = value;
}
#include <new>
#include <string.h>

class TestA
{
    private:
        char *Array;
    public:
        TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
        ~TestA(){if(Array != NULL){ delete [] Array;} }

        char * const GetArray(){ return Array; }
};

int main()
{
    TestA Temp;
    printf("%s\n",Temp.GetArray());
    Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
    Temp.GetArray()[1] = ' '; 
    printf("%s\n",Temp.GetArray());
}
int main()
{
    TestA Temp;
    printf("%s\n",Temp.GetArray());
    Temp.GetArray()[0] = ' ';
    Temp.GetArray()[1] = ' ';
    printf("%s\n",Temp.GetArray());
    Temp.GetArray() = NULL; //Bwuahahahaa attempt to set it to null
}
int main()
{
    TestA Temp;
    printf("%s\n",Temp.GetArray());
    Temp.GetArray()[0] = ' ';
    Temp.GetArray()[1] = ' ';
    printf("%s\n",Temp.GetArray());
    delete [] Temp.GetArray(); //Bwuahaha this actually works!
}
class TestA
{
    private:
        char *Array;
    public:
        TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
        ~TestA(){if(Array != NULL){ delete [] Array;} }

        char * const &GetArray(){ return Array; } //Note & reference operator
        char * &GetNonConstArray(){ return Array; } //Note non-const
};

int main()
{
    TestA Temp;
    Temp.GetArray() = NULL; //Returns error
    Temp.GetNonConstArray() = NULL; //Returns no error
}
class TestA
{
    private:
        char *Array;
    public:
        TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
        ~TestA(){if(Array != NULL){ delete [] Array;} }

        char * const &GetArray(){ return Array; }

        void ModifyArrayConst(char * const Data)
        {
            Data[1]; //This is okay, this refers to Data[1]
            Data--; //Produces an error. Don't want to Decrement that.
            printf("Const: %c\n",Data[1]);
        }

        void ModifyArrayNonConst(char * Data)
        {
            Data--; //Argh noo what are you doing?!
            Data[1]; //This is actually the same as 'Data[0]' because it's relative to Data's position
            printf("NonConst: %c\n",Data[1]);
        }
};

int main()
{
    TestA Temp;
    Temp.ModifyArrayNonConst("ABCD");
    Temp.ModifyArrayConst("ABCD");
}
int main()
{
    int A = 10;
    int * const B = &A;
    *B = 20; //This is permitted
    printf("%d\n",A);
    B = NULL; //This produces an error
}
const int X=1; or
int const X=1;
const int* ptr = &X;
int* const ptr = &X;
void func (int*const* ptrptr)
const int* const ptr=&X;
void MyClass::func (void) const;
int const x; x=4; //you can assign its value only One time const int* ptr = &X; //Here pointer variable refer contents of 'X' that is const Such that its cannot be modified int* const ptr = &X; //Here pointer variable itself is constant Such that value of 'X' can be modified But pointer can't be modified