何时在C ++中使用指针指针?

时间:2015-04-24 13:31:46

标签: c++

我想知道我们何时在C ++中使用Pointer to Pointer以及为什么我们需要指向指针?我知道当我们指向一个指针时,这意味着我们将变量的内存地址保存到内存中,但我不知道为什么需要它?另外我看到一些例子总是使用Pointer-to-pointer来创建 Matrix !但为什么Matrix可能需要Pointer to Pointer?

6 个答案:

答案 0 :(得分:6)

  

何时在C ++中使用指针指针?

我认为最好永远不要在C ++中使用它。理想情况下,在处理C API或一些遗留的东西时,您只会必须使用它,仍然与C API相关或设计C / API。

指针指针几乎已被C ++语言功能和附带的标准库淘汰。你有想要传递指针和编辑函数中原始指针的时间的引用,对于像指向字符串数组的指针这样的东西你最好使用std::vector<std::string>。这同样适用于多维数组,矩阵等等,C ++有更好的方法来处理这些事情,而不是指针的神秘指针。

答案 1 :(得分:1)

你之前可能已经看过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)();

虽然这不是双指针的真正用途,但这是应用它们的一个主要例子。双指针最常见的地方是黑客攻击和逆向工程,你通常需要在内存中找到一个指针并改变它所指向的内容。

答案 2 :(得分:1)

如果要将传递给函数的变量值更改为函数参数,并在该函数外部保留更新值,则需要指向该变量的指针(单指针)。

void modify(int* p)
{
  *p = 10;
}

int main()
{
  int a = 5;
  modify(&a);
  cout << a << endl;
}

现在,当您想要将传递给函数的指针值更改为函数参数时,需要指向指针的指针。

简单来说,如果要在函数调用之外保留(或保留更改)Memory-Allocation或Assignment,请使用**。 (所以,用双指针arg传递这样的函数。)

这可能不是一个很好的例子,但会向您展示基本用途:

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;
}

答案 3 :(得分:1)

当我们想要改变它所指向的指针的地址时,我们基本上需要指向指针。一个非常好的例子是链表的情况,当我们尝试时,我们发送一个指针指向头节点的指针在开头插入一个值。代码片段粘贴在下面。

 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。 在这种情况下,传递指向指针的指针。

答案 4 :(得分:1)

任何时候您都在处理C库。 C中同一个问题有两个常见的答案:

首先,任何时候你想要双下标数组,如:

int main(int argc, char** argv) 

其次,任何时候你想要一个函数的另一个返回值。 libgit2中有许多函数可以执行此操作,因为它们希望返回有意义的错误类型,而不仅仅是null,例如git_branch_create中的第一个参数。

当然,您可以返回两个struct项,但这通常需要两行代码。实际上,指向指针的指针允许您将指针直接写入它所居住的结构中。

在C ++中,只要存在合适的C ++数据类型,就可以避免直接使用指针,而我的libgit2示例包含在C ++的例外中,但是......

你不能从大多数高级语言中调用C ++,所以如果你要编写一个你想要的库,比如Perl,Python和C ++,那么你用C语言编写它。

答案 5 :(得分:0)

假设你想在C ++中实例化一个对象......

MyClass * obj = new MyClass();

您必须这样做,因为new返回指向动态内存中已分配对象的指针。以下是错误的:

MyClass obj = new MyClass(); // wrong. 'new' returns a pointer.

假设你想要一个对象数组......

MyClass ** objArray = new MyClass*[10];