何时在C++中使用指向指针的指针
When to use Pointer-to-Pointer in C++?
我想知道我们在C++中什么时候使用指针对指针,为什么我们需要指向指针?我知道当我们指向一个指针时,这意味着我们将变量的内存地址保存到内存中,但我不知道为什么我们需要它?我还看到了一些例子,在创建矩阵时总是使用指针到指针!但是为什么矩阵可能需要指针对指针呢?
何时在C++中使用"指向指针"?
我认为最好不要在C++中使用它。理想情况下,在处理C API或一些遗留的东西时,您只需要使用它,这些东西仍然与C API相关或在设计时考虑到了C API。
由于C++语言的特性和附带的标准库,指针对指针已经过时了。当你想传递一个指针并编辑函数中的原始指针时,你有引用,对于像指向字符串数组的指针这样的东西,你最好使用std::vector<std::string>
。这同样适用于多维数组、矩阵等等,C++有一种比隐指针到指针更好的方法来处理这些事情。
如果要更改作为函数参数传递给函数的变量的值,并在该函数之外保留更新后的值,则需要指向该变量的指针(单指针)。
void modify(int* p)
{
*p = 10;
}
int main()
{
int a = 5;
modify(&a);
cout << a << endl;
}
现在,当您想更改作为函数参数传递给函数的指针的值时,您需要指向指针的指针。
简单地说,当您希望在函数调用之外保留(或保留对内存分配或分配的更改)时,请使用**
。(所以,用双指针参数传递这样的函数。)
这可能不是一个很好的例子,但将向您展示基本用途:
void safe_free(int** p)
{
free(*p);
*p = 0;
}
int main()
{
int* p = (int*)malloc(sizeof(int));
cout << "p:" << p << endl;
*p = 42;
safe_free(&p);
cout << "p:" << p << endl;
}
当我们想要更改它所指向的指针的地址时,我们基本上需要指针对指针。非常好的例子是链表的情况,当我们试图在开头插入值时,我们将指针对指针发送到头节点。粘贴在下面的代码段。
int main()
{
/* Start with the empty list */
struct node* head = NULL;
/* Use push() to construct below list
1->2->1->3->1 */
push(&head, 1);
push(&head, 2);
.....
....
}
/* Given a reference (pointer to pointer) to the head
of a list and an int, push a new node on the front
of the list. */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node = (struct node*) malloc(sizeof(struct node));
.....
.....
}
这基本上是因为,比如说一个指针最初指向一个内存位置0X100
,我们想把它改为指向其他位置,比如0X108
。在这种情况下,将传递指针到指针。
你可能以前见过int main(),你见过这个吗:
int main(int argc, char** argv)
argv实际上是一个双指针,它实际上不是双指针,但它是指向指针数组的指针,每个指针指向与命令行参数相关的字符数组。
这不是最好的例子,因为你可能想要一个更实际的例子。我会写一个更好的例子并编辑我的帖子:)
编辑:
如果您熟悉类和虚拟函数,那么您可能还知道,任何具有虚拟函数的类都会自动获得_vftp成员变量。
_vftp成员是指向虚拟函数的所有函数指针列表的指针。它插入在结构的最开始。如果您按照以下方式创建了一个新对象:
class myclass
{
public:
//void *_vftp; this is where the _vftp member gets inserted automatically
virtual void vfunc1();
};
void myclass::vfunc1() {printf("yay");}
void main() {
myclass *pMyObject = new myclass();
}
在实例化myclass时,_vftp被添加到对象结构中,它是第一个变量。因为pMyObject是指向内存中此结构的指针,所以*pMyObject等同于_vftp。
因为_vftp是指向虚拟函数指针数组的指针,所以*_vftp等于vfunc1(函数指针)。
这意味着,如果我们两次取消引用pMyObject,并调用它,我们将调用vfunc1():
typedef (void* (__thiscall* fnVFunc1))(void);
((fnVFunc)**pMyObject)();
虽然这不是双指针的真正用途,但这是应用它们的一个主要示例。双指针最常见的地方是黑客攻击和逆向工程,在那里你通常需要在内存中找到一个指针,并改变它指向的任何东西
在处理C库的任何时候。对于C中的同一个问题,有两个常见的答案:
首先,任何时候你想要双下标数组,比如:
int main(int argc, char** argv)
第二,只要您想要函数的另一个返回值。libgit2中有许多函数这样做是因为它们希望返回一个有意义的错误类型,而不仅仅是null
,例如git_branch_create中的第一个参数。
当然,您可以返回一个两项struct
,但这通常是额外的两行代码。事实上,指针对指针允许您将指针直接写入它所在的结构中。
在C++中,只要存在合适的C++数据类型,就应该避免直接使用指针,我的libgit2示例也包含在C++的异常中,但是。。
你不能从大多数高级语言中调用C++,所以如果你正在编写一个库,你想用Perl、Python和C++来使用,那么你就用C.来编写它
假设您想在C++中实例化一个对象。。。
MyClass * obj = new MyClass();
您必须这样做,因为new
会返回一个指向动态内存中已分配对象的指针。以下是错误的:
MyClass obj = new MyClass(); // wrong. 'new' returns a pointer.
假设您想要一组对象。。。
MyClass ** objArray = new MyClass*[10];
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错