代码之家  ›  专栏  ›  技术社区  ›  Brian T Hannan

在C/C++项目中,指针指针和/或指向指针最有用的时间是什么?

  •  1
  • Brian T Hannan  · 技术社区  · 15 年前

    一开始,指向指针的指针和指向指针的引用似乎过于复杂,特别是对于新手。在你从事的C/C++项目中使用了哪一个是最好的和最有用的理由?

    这可以帮助人们更好地理解指针以及如何有效地使用它们。

    编辑:包括C和C++

    11 回复  |  直到 15 年前
        1
  •  2
  •   Stack Overflow is garbage    15 年前

    由于还没有人提到这一点,它们作为迭代器可能很有用。

    假设您有某种类型的对象列表。你需要以特定的顺序遍历其中的一些。

    因此,创建一个数组,其中包含指向需要遍历的对象的指针,然后对该数组进行排序。

    该数组的迭代器是指向指针的指针。

    把它分类 std::sort 需要一对迭代器,这意味着它需要一对指向指针的指针。

    然后用 std::for_each 还需要一对迭代器。

    这就是我上次使用指针指向指针的上下文。(实际上我有最后一个抽象层,所以我最终得到了指向指向指针的指针,但这可能更不寻常)

        2
  •  4
  •   John Dibling    15 年前

    指向指针的指针通常用作分配和返回缓冲区的参数,如字符串:

    void SetValue(char** buf)
    {
        string s = "Hello, Ptr Ref";
        *buf = new char[s.length()+1];
        copy(s.begin(), s.end(), *buf);
        (*buf)[s.length()] = 0;
    }
    
    
    int main()
    {
        char* buf = 0;
        SetValue(&buf);
        cout << buf;
        delete [] buf;
        return 0;
    }
    

    同样,您可以传递对该缓冲区的引用,而不是传递指向要分配和修改的缓冲区指针的指针。这有助于向调用者澄清函数的语义,这样它们就不会执行类似调用的操作。 SetValue(0);

    void SetValue(char*& buf)
    {
        string s = "Hello, Ptr Ref";
        buf = new char[s.length()+1];
        copy(s.begin(), s.end(), buf);
        buf[s.length()] = 0;
    }
    
    
    int main()
    {
        char* buf = 0;
        SetValue(buf);
        cout << buf;
        delete [] buf;
        return 0;
    }
    

    但即使是语义 SetValue(char*&) 可能比 SetValue(char**) 版本,还有改进的空间。想到了谁拥有结果指针的问题。

    请记住,虽然这些示例是简单的和人为的,但是像这样的实现却比比皆是。在许多这样做的情况下,您没有选择——例如,在调用类似这样的winapi函数时 FormatMessage() 并要求它分配缓冲区。但在编写函数的许多其他情况下,将有其他方法来剥除猫的皮。可以说,更好的方法。例如:

    string GimmeValue()
    {
      return "Hello, String";
    }
    

    由于各种原因,这可能会更好。从语义上讲,按值返回值比使用指针指向指针之类的outvals更清楚,因为所有权问题很容易解决。通常最好避免在堆栈分配变量做得很好的地方使用new操作符,因为这样可以避免由于 delete 多次使用缓冲区。

        3
  •  2
  •   Jacob    15 年前

    指向指针的指针?动态分配的二维阵列!

        4
  •  2
  •   Jerry Coffin    15 年前

    我几乎记不清上次我直接用过哪一个。大多数情况下,它们对于实现自己的容器类很有用——例如,如果要在链接列表中分配一个节点,则在节点之间有指针,如果要修改传递给函数的指针,则需要引用或指向该指针的指针。

    当然,也可以使用指向指针的指针来创建伪二维数组。如果你真的需要一个正方形的数组,它们不是一个特别好的选择,但是如果你想要一个“不规则的数组”(例如一个字符串数组,每个字符串的长度可能不同),它是有用的。

    指针在C中几乎是不可避免的,但是在C++中,标准库已经有容器类了。例如,如果你想在C中动态数组的动态数组,那么你的唯一选择就是从A开始。 char ** 并动态分配工件。在C++中,通常需要使用 std::vector<std::string> 相反。当/如果您决定实现自己的容器时,仍然会遇到它们,但这是非常罕见的情况(至少您必须从原始指针开始,而不是在现有容器之上构建)。

        5
  •  1
  •   wheaties    15 年前

    传递代表TIFF文件内容的值数组以进行地理处理。

        6
  •  0
  •   Anon.    15 年前

    假设您想要返回一个已分配的缓冲区,或者您可能需要重新分配一个传入的缓冲区。

    您可以返回一个指向缓冲区的指针,或者让调用者传入一个指针的地址(这样您就有了指向指针的指针),然后将该指针设置为指向缓冲区。

        7
  •  0
  •   Ruddy    15 年前

    任何返回接口的方法都必须被赋予指向指针参数的指针才能返回。

        8
  •  0
  •   Richard Pennington    15 年前

    我曾经在函数中使用char***arg参数来更新一个动态分配的argv-like数组,还把begebies从我的同事中吓跑。

        9
  •  0
  •   jason    15 年前

    好, char **argv 动态分配的二维交错数组通常都非常有用。

    每当您希望被调用方更改指针(而不是指针指向的对象)时,对指针的引用都很有用。例如,动态提供内存的人:

    void feedMeSeymour(void *&p, int size) {
        p = new char[size];
    }
    
        10
  •  0
  •   mholzmann    15 年前

    指向指针的指针也适用于创建混合长度数组的数组。我想它们通常被称为 固执的 锯齿状阵列。我以前用过这个来减少嵌入式系统的内存使用。

        11
  •  0
  •   Igor Zevaka    15 年前

    模板排序向量的排序函数。这是一个相当现实的例子:

    template <typename T>
    class Vector {
    public:
        typedef bool SortFunc(const T& left, const T& right) ;
        void SetSort(SortFunc* pFunc){}
    };
    
    
    bool intSort(const int& left, const int& right)
    {
        return true;
    }
    
    bool pintSort( int* const & left, int* const & right)
    {
        return true;
    }
    
    //in main
    
    Vector<int> intVec;
    Vector<int*> pintVec;
    
    intVec.SetSort(&intSort);
    pintVec.SetSort(&pintSort);
    

    考虑到我们可以将任何东西作为向量参数传递,使用常量引用作为排序函数参数是相当明智的。然而,什么是不健全的,是解决如何串血腥的星号,符号和 consts 为了达到 对非常量整数指针的常量引用 .