C++指向常量指针的指针
C++ pointer to const pointer
我仍然混淆了在具有多个间接寻址的指针中放置const
的位置。有人可以澄清一下吗?
例如,现在我需要一个指向 const 指针的指针,这意味着我可以为其分配int *pTargets
变量int **ppTargets
这样的变量,例如:
int foo(int **ppTargets) {
int *pTargets = /* calculate here */;
*ppTargets = pTargets;
return 37; // just e.g.
}
上面的代码缺少const
。所以在foo
我希望pTargets
指向常量内存并且在初始化后不可分配(这样就不能写例如pTargets++
),那将是int const *const pTargets = /* assigned once */
.接下来,我想声明ppTargets
ppTargets
本身可以分配,但*ppTargets
只能读取。
换句话说,在我想要的调用方代码中:
int const* pTargets;
foo(&pTargets);
我试图按如下方式声明foo
,但you cannot assign to a variable that is const
出现错误:
int foo(int *const *const ppTargets)
我总是从最右边的变量名向左读取 C/C++ 定义。
所以:
-
const char *p;
p
是指向const
char
的指针所以
p
可以修改,但*p
不能。 -
const char * * const p = &a;
p
是一个指向const
char
的指针的const
指针。所以
p
不能修改(因此我初始化了它);*p
可以;但**p
不能。
[编辑 - 为完整性添加了数组]
-
const char * * const p[4] = { &a, &b, &c, &d };
,其中包含指向...p
是一个 4 元素const
数组
您要查找的是int const * const * ppTarget
。不,等等,你正在寻找int const ** const ppTarget
.不不,这是int * const * const * ppTarget
.
其中之一可能是正确的(我打赌第一个)。但是,您不希望阅读您的代码的人猜测您的意思。实在是太混乱了。C++可以这样对你。
你应该做的是使用typedef
来确保阅读代码的人理解你想要什么。
typedef const int *CINT_PTR;
CINT_PTR pTarget = ....;
CINT_PTR *ppTarget = &pTarget;
由于pTargets
是一个const int *
,它的地址是一个const int **
,这是你想要的函数参数类型:
int foo(const int **ppTargets)
{
int *pTargets = malloc(sizeof(int)*4);
pTargets[0] = 1;
pTargets[1] = 2;
pTargets[2] = 3;
pTargets[3] = 4;
*ppTargets = pTargets;
return 37;
}
int main()
{
int const *pTargets;
foo(&pTargets);
return 0;
}
编辑:
如果要设置的变量定义为int const * const pTargets;
,则设置它的唯一方法是在初始化时。 然后,您可以改为执行以下操作:
const int *foo2()
{
int *pTargets = malloc(sizeof(int)*4);
pTargets[0] = 1;
pTargets[1] = 2;
pTargets[2] = 3;
pTargets[3] = 4;
return pTargets;
}
int main()
{
int const * const pTargets = foo2();
return 0;
}
所以我希望
pTargets
指向常量内存并const
它本身, 那将是int const *const pTargets = /* assigned once */
.下一页 I 想要声明ppTargets
可以分配ppTargets
本身,但是 那么*ppTargets
只能被读取。
不幸的是,这是没有意义的。 您的示例代码分配给*ppTargets
,这确实似乎是函数foo()
的主要目标。 如果*ppTargets
可以分配一次,则可以再次分配。
目前还不清楚为什么你希望foo()
的局部pTargets
被const
,而不是只是不修改它,但你可以为相应的非const
-qualifed类型的对象分配一个const
值。 因此,您实际上正在寻找的可能是
int foo(int const **ppTargets) {
int const * const pTargets = /* calculate here */;
*ppTargets = pTargets;
return 37; // just e.g.
}
这似乎与您的预期用途一致:
换句话说,在我想要的调用代码中:
int const* pTargets; foo(&pTargets);
对于任何类型的T
,指向T
的指针的类型可以拼写为T *
。 特别是,此&pTargets
的类型是int const **
(看起来很熟悉?),这是函数参数的适当类型,函数应该能够通过该类型设置调用方pTargets
的值。
再说一次,调用foo()
让它设置调用方pTargets
的值似乎正是重点。 如果应该阻止foo()
这样做,那么理想的方法是传递pTargets
本身(按值),而不是传递其地址并争论const
限定符。
所以我希望 pTarget 指向常量内存并成为常量本身
接下来我想声明 ppTargets 可以分配 ppTargets 本身,但随后只能读取 *ppTargets。
为了清楚起见,int const *
Ptr
,让int const * const
(即Ptr const
)CPtr
.
就像你正确写int const *const pTargets
一样(即CPtr
),当您想要一个指向 const int 的 const 指针时,当您想要一个指向 const int 的 const 指针的非 const 指针时也是如此(即&pTargets
的类型,即CPtr*
),你需要int const *const * ppTargets
。请注意,Ptr*
将隐式转换为CPtr*
。
您尝试的int *const *const ppTargets
将是一个常量指针,指向常量指针到非常量整数。由于类型是常量指针,因此无法分配与您的要求相矛盾的赋值。
更一般地说,一个简单的经验法则是从右到左读取 C 指针类型声明,恒常性适用于关键字的左侧(除非它是最左侧的标记,在这种情况下它适用于右侧)。
现在我们已经找到了满足您声明要求的类型,让我提请您注意您对*ppTargets = pTargets
foo
实现。这与"*ppTargets
只能阅读"的要求相矛盾。
在其他人的输入之后,特别是顺时针/螺旋规则 @Mahesh 以及一些辩论,我明白了如何轻松阅读和编写这些东西。
我们应该看看什么可以修改,什么不能修改。因此,请考虑不带const
s:int **ppTargets
的声明。我们希望ppTargets
本身不能修改,而*pTargets
可以修改,而**pTargets
不能修改。
然后,从右到左应用这些观察结果:int const * * const ppTargets
.
最右边的const
说ppTargets++
是不可能的。
然后中间没有const
说明(*ppTargets)=pTargets
是可能的。
然后另一个最左边的const
说(**ppTargets)++
是不可能的。
在我看来,间接寻址的基本形式化是
(read-only|read-write) <memory zone> * (read-only|read-write) <pointer>
其中<pointer>
本身就是一个记忆区。 对于双向间接,表达式变为
(read-only|read-write) <memory zone> * (read-only|read-write) <memory zone/pointer-level2> * (read-only|read-write) <pointer-level1>
使事情更难以理解的是放置限定符的可能性(例如。read-only
) 在符号左侧大小的 OR 之后<memory zone>
*
。在符号*
右侧,限定符只能放在<pointer>
之前。
在C++read-only
表示常量,read-write
是隐式限定符。
因此,我们可以拥有:
char* p
读写char
内存区域的读写指针const char* p
指向只读char
内存区域的读写指针char* const p
指向读写char
内存区域的只读指针const char* const p
指向只读char
内存区域的只读指针
然后我们可以在基本类型结果等效声明之后移动const
:
char const* p
指向只读char
内存区域的读写指针char const* const p
指向只读char
内存区域的只读指针
与目标指针相比,允许指针转换在每个间接寻址级别的源指针中具有相等的限定符或限制较少的限定符。
因此,以下情况有效:
int foo(const int* const* const p);
{// equal leftmost qualifier
const int* p = nullptr;
const int** p1 = &p; // 2nd and 3rd qualifiers are less restrictive
foo(p1);
const int* const* p2 = &p; // 2nd qualifier is equal, 3rd one (implicit read-write) is less restrictive
foo(p2);
const int* const* const p3 = &p; // 2nd and 3rd qualifiers are equal
foo(p3);
}
{// less restrictive leftmost qualifier of p
int* p = nullptr;
int** p1 = &p; // 2nd and 3rd qualifiers are less restrictive
foo(p1);
int* const* p2 = &p; // 2nd qualifier is equal, 3rd one (implicit read-write) is less restrictive
foo(p2);
int* const* const p3 = &p; // 2nd and 3rd qualifiers are equal
foo(p3);
}
在您的情况下,作为参数传递的指针最左边的限定符 (&pTargets
) 不等于或小于函数中指针最左边foo
限定符的限制。
- 将常量指针引用绑定到非常量指针
- 如何使用数据对象上的常量指针初始化类
- C++中的指针和常量问题不大
- 为什么我收到"从常量指针到指针的转换无效?
- 当成员值从指针更改为非指针时,C++常量问题
- 使用双指针传递 2D 常量数组
- C++/QT:使用指向私有成员的常量指针作为只读数据共享
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 模板推导:为什么函数指针模板定义在常量和/或引用时不匹配?
- 初始化指针的常量向量
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 什么是常量指针常量引用类型的参数?(const X* const & p)
- 无法将"常量指针常量"传递给常量引用
- C++:如何创建一个临时对象,包含一个指针 - 常量或非常量,具体取决于上下文
- 具有函数指针常量数组的 C++ 模板化静态类
- 这个constexpr整数不是空指针常量吗
- 使指针常量C++
- C++11在stl容器中共享指针常量
- 空指针常量转换为右值
- 在参考 (T&) 和常量指针 (T* 常量) 之间进行选择