在c++中声明指针指向指针的效率

Efficiency of declaring a pointer to a pointer in C++

本文关键字:指针 效率 声明 c++      更新时间:2023-10-16

这听起来像是一个小问题,但是在我创建的程序中,我有一个递归函数,在这个函数中我声明了一个指向类'QuadTree'的指针的指针。

。:

void check_tree(QuadTree* p_qtree, Object* p_obj)
{
  if (!p_qtree->is_leaf())
  {
    QuadTree** children = p_qtree->get_children();  // <-- WHAT I'M REFERRING TO
    for (int i = 0; i < 4; i++)
      check_tree(children[i], p_obj);
  }
  else
  {
    ...
  }
}

在递归函数中声明"四叉树**"是否会因为重复调用函数而降低程序的效率,或者其影响可以忽略不计?像下面这样在函数外声明它更好吗?

QuadTree** children;   // <-- MOVE DECLARATION TO HERE
void check_tree(QuadTree* p_qtree, Object* p_obj)
{
  if (!p_qtree->is_leaf())
  {
    children = p_qtree->get_children();
    for (int i = 0; i < 4; i++)
      check_tree(children[i], p_obj);
  }
  else
  {
    ...
  }
}

我最初的想法是在递归函数中声明指向指针的指针的影响可以忽略不计,因为它只为指针而不是整个类分配内存,但我不太确定。

性能方面,分配大小为n的堆栈和大小为m的堆栈之间没有区别(它们都编译为读取寄存器,添加常量值,并将值存储回相同的寄存器)。

内存方面,通过在函数内声明变量,每层堆栈将使用额外的8字节(64位机器)或4字节(32位机器)。国际海事组织,可以忽略不计。而且,编译器可以在安全的情况下将其优化掉。

正确性方面,在外部分配内存使函数不可重入。当您使用多个线程时,这可能是一个问题。

这种行为被称为二星编程,通常被认为是不好的。

你可以很容易地用引用代替(既"高性能"又可读):

void check_tree(QuadTree& p_qtree, Object& p_obj) {
    if (!p_qtree.is_leaf()) {
        QuadTree& children = p_qtree.get_children();  // should return a reference to QuadTree
        for (int i = 0; i < 4; i++)
            check_tree(children, p_obj);
    }
    // ...
}

就性能而言,每个指针都是额外的间接层。但是编译器优化的方式是无限的

在这种情况下,在外部声明它会导致一个bug:当第二次递归调用check_tree时,如果在另一个非叶子变量中有一个非叶子变量,则children变量将被覆盖。

check_tree
   children = something
   recursive check_tree when i=0
       children = overwritten with something
   recursive check_tree when i=1 -> has the incorrect "children".