http://www.parashift.com/c++-faq-lite/constptrptr-conversion.html 写道
[18.17] Why am I getting an error converting a Foo** → Foo const**?
Because converting Foo** → Foo const** would be invalid and dangerous.
C++ allows the (safe) conversion Foo* → Foo const*, but gives an error if you try to implicitly convert Foo** → Foo const**.
The rationale for why that error is a good thing is given below. But
first, here is the most common solution: simply change Foo const** to
Foo const* const*:
class Foo { /* ... */ };
void f(Foo const** p);
void g(Foo const* const* p);
int main()
{
Foo** p = /*...*/;
...
f(p); // ERROR: it's illegal and immoral to convert Foo** to Foo const**
g(p); // OK: it's legal and moral to convert Foo** to Foo const* const*
...
}
The reason the conversion from Foo** → Foo const** is dangerous is that
it would let you silently and accidentally modify a const Foo object
without a cast:
class Foo {
public:
void modify(); // make some modification to the this object
};
int main()
{
const Foo x;
Foo* p;
Foo const** q = &p; // q now points to p; this is (fortunately!) an error
*q = &x; // p now points to x
p->modify(); // Ouch: modifies a const Foo!!
...
}
If the q = &p line were legal, q would be pointing at p. The next
line, *q = &x, changes p itself (since *q is p) to point at x. That
would be a bad thing, since we would have lost the const qualifier: p is
a Foo* but x is a const Foo. The p->modify() line exploits p's
ability to modify its referent, which is the real problem, since we
ended up modifying a const Foo.
By way of analogy, if you hide a criminal under a lawful disguise, he
can then exploit the trust given to that disguise. That's bad.
Thankfully C++ prevents you from doing this: the line q = &p is
flagged by the C++ compiler as a compile-time error. Reminder: please do
not pointer-cast your way around that compile-time error message. Just
Say No!
(Note: there is a conceptual similarity between this and the prohibition against converting Derived** to Base**.)
实际上 形参改为 类似 char const * const *的形式,C中也照样warning。C++中无warning
分享到:
相关推荐
### 二级指针申请空间详解 #### 一、引言 在C语言中,指针是一种非常重要的数据类型,它提供了灵活的操作内存的方式。而二级指针是指向指针的指针,它允许我们间接地操作内存地址。本文将通过一个具体的示例代码来...
- 分析:`p`是一个指向`const int *`类型的二级指针。 - 步骤1:`const int *(*p)` 表明`p`是一个指向`const int *`类型的指针。 - 步骤2:`const int (*(*p))` 表明`*p`是一个指向`const int`类型的指针。 - ...
"指针进阶之数组参数和指针参数" 指针在编程语言中是一个非常重要的概念,了解指针的概念和使用方法是编程语言的基础。今天我们将深入探讨指针在...总结:在传递指针参数时,函数的参数可以写成一级指针或二级指针。
例如,函数可以接收一个二级指针参数,然后通过它来重新分配内存或改变一级指针的指向。 总之,C语言中的二级指针是一个强大的工具,它提供了对内存的深层操作能力。理解和熟练使用二级指针是提升C语言编程技能的...
例如,`int **pp`是一个二级指针,它可以指向一个`int *`类型的指针。这种机制常用于实现动态内存分配的链表或树结构。 ### 8. 函数指针 函数指针是能够指向函数的指针。通过函数指针,我们可以将函数作为参数传递...
- const指针和指针const:理解const关键字在指针上下文中的含义,包括const修饰指针和指针所指对象的区别。 - 指针安全:讨论指针未初始化、空指针、野指针等问题,以及如何避免这些潜在的错误。 3. **彻底搞定C...
- `const`变量可以作为数组大小等常量表达式的参数。 ```c const int size = 100; int array[size]; // 合法:size是常量表达式 ``` 2. **复合声明**: - `const`可以与指针复合使用,形成多种不同的含义。 ...
2. **二级指针的应用**:例如,在实现动态二维数组时,可以使用二级指针来存储每一行的起始地址。 #### 函数名与函数指针 1. **函数指针的声明**:函数指针是一种特殊的指针,它可以存储函数的地址,从而可以在...
例如,`int **pp`是一个二级指针,可以用来存储指向指针的指针。 4. **指针与引用**:比较指针和引用的异同,它们都是间接访问变量的方式,但引用不具有NULL状态,且一旦初始化后不能改变引用的对象。 5. **动态...
5. **指针的多级引用**:二级指针、三级指针等可以用来间接访问更深层次的数据结构,如多维数组或嵌套结构体。理解多级指针是解决复杂数据结构问题的关键。 6. **指针与指针数组**:指针数组是数组的元素是指针,它...
这有助于增强代码的可读性和安全性,同时允许将const对象作为参数传递给这些函数。 2. **const对象的限制**: const对象只能调用其类中的const成员函数,这进一步增强了代码的安全性,确保了数据的完整性。 #### ...
本章节主要讲解了指针的使用,特别是与字符串相关的操作,包括字符串数组、字符串指针以及const关键字的应用。 ### 1. 字符串数组和字符串指针 字符串数组是字符数组的特例,用于存储字符串。例如,`char name[20]...
7. **const指针与指针const**:理解`const`关键字在指针上下文中的不同用法,包括常量指针、指针常量和完全常量指针。 8. **指针与指针的指针**:探索多级指针的概念,如何通过二级或更高级别的指针间接访问内存。 ...
我们还可以声明指向指针的指针,即二级或多级指针,用于实现更复杂的内存管理: ```c++ int *pInt = # int **ppInt = &pInt; ``` 5. **指针运算** 指针可以进行加减运算,增加或减少特定数量的字节,移动...
该软件提供了丰富的练习题库和模拟测试,覆盖了二级C语言考试的所有核心知识点,包括基本语法、数据类型、控制结构、函数、数组、指针、结构体等。 一、基本语法 二级C语言的基础是掌握其语法,包括变量声明、常量...