代码之家  ›  专栏  ›  技术社区  ›  John

C或C++中的未初始化指针有使用吗?

  •  4
  • John  · 技术社区  · 15 年前

    在其中一条评论中 this question 默认情况下初始化C++指针会破坏与C的兼容性。

    没关系,但为什么会有这样的事情?我想只有我 通缉犯 由于某种原因未初始化的指针。但我想不出我为什么要那样做的原因。

    是否使用未初始化的指针?或者兼容性问题仅仅是一种兼容行为(即不增加开销),而不是破坏代码?

    10 回复  |  直到 15 年前
        1
  •  17
  •   Community CDub    7 年前

    这是一个非常专业的视频游戏优化案例(基本上是一个嵌入式系统)。我们曾经在我们的电子游戏中使用它们来加载就地数据行为,以加速加载(并避免碎片化)。

    基本上,我们将在PC炊具中创建控制台端(PlayStation)对象。然后,为了减少碎片过载,我们将用一个alloc将数据对象打包到一个连续的缓冲区中。然后,将更改对此缓冲区中数据对象的引用,以从指向偏移量的指针中减去基值(unfix调用——我们还有一个虚拟的fix/unfix调用,该调用占用缓冲区基值,并且可以在偏移量和指针之间进行转换)。

    当我们加载数据时,它被加载到一个大的块中。根引用的所有数据都来自根对象。我们可以在根目录上执行一个就地“new”,它将为对象初始化适当的vf表并修复所有附加的块(分别执行inplace new和fixing up attached blocks)。

    我们需要调用(就地新的)构造函数来在对象中生成适当的VF表。但是,如果在构造函数期间指针被自动清除为空,我们将丢失偏移数据,并且无法在连续块中的对象之间重新创建指针。


    fwiw,这是电子游戏世界中常见的一种技术。这个 Gamasutra article (不是我或我的同事写的)详细解释了他们在另一家公司所做的类似事情:

    另外,这个话题的讨论 SourceForge .

    甚至有几个GDC( Game Developer Conference )讨论这个问题。

    在Google上搜索“就地加载”将提供许多其他使用这种技术的人的例子,这种技术基本上需要未初始化的指针。


    注意:当前,这是唯一回答实际问题的答案(“C或C++中没有初始化的指针使用吗?”)通过为必须保持统一的指针提供特定的用途。

    所有其他的回答都是 original question referenced ([C++]为什么默认情况下初始化为空的指针?)这引起了海报问这个问题。

        2
  •  11
  •   Pavel Minaev    15 年前

    首先,默认情况下初始化指针(或任何其他变量)不会破坏C.和C++两种状态的兼容性,即未初始化变量的值是不确定的;实际上,这意味着它可以保存任何值(包括陷阱表示),但请注意 0 属于“任意值”的集合!所以一致的实现可以很好地初始化所有指向 . 然而,您的程序,如果依赖于它,将不会是一致的。

    现在,关于为什么您可能希望指针不被初始化:主要是在以后写入时。例如:

    void foo(int*& p) {
       p = new int;
    }
    
    int* p; // why initialize? we overwrite it anyway
    foo(p);
    

    您可以说编译器应该能够优化这一点。不幸的是,如果 foo 不可用(例如,禁用全局链接时间优化;或者启用了全局链接时间优化,但函数位于DLL中),因为它不知道 将尝试读取 p (然后需要初始化),或者如果它只是写入(然后不需要初始化)。更重要的是,有些案例可能难以分析,例如:

    bool try_parse_int(const char* s, int& n)
    {
        // if parsed successfully, assign result to n and return true
        // if there was error parsing, don't touch n and return false
        ...
    }
    
    int n;
    if (try_parse_int(s, n)) {
        // use n here
        ...
    } else {
       // don't use n here
       ...
    }
    

    即使编译器对所有函数都有完整的定义,它也很难进行分析。

        3
  •  8
  •   Mark Ransom    15 年前

    初始化指针需要一些时间。大多数时候你不应该关心这个问题,但是很少有时候它会起作用。C(和扩展C++)的指导原则之一是 永远不要让你为你不需要的东西付钱 不要为你不使用的东西付钱。

    另一种罕见的情况可能出现在嵌入式编程中,其中变量对应于硬件寄存器。将一个值放入寄存器将启动硬件执行一些可能会有损健康的操作。

        4
  •  6
  •   anon    15 年前

    用于统一指针?请参见std::strtol()。

    char * bad;
    long n = std::strtol( "123xyz", &bad, 10 );
    

    此调用后,BAD将包含指向“X”的指针。初始化它没有意义。

        5
  •  2
  •   Bill K    15 年前

    如果你在C++中编写一个C风格的程序,但是假设指针被初始化,然后把程序返回到一个C编译器,它将无法工作。这是我能想象它重要的唯一原因。

        6
  •  2
  •   caf    15 年前

    不会 中断与C的兼容性-一种C实现,其中所有未初始化的指针实际上都初始化为0(或者实际上是初始化为任何内容!)完全符合要求。

        7
  •  1
  •   KeatsPeeks    15 年前

    不必为你不需要的东西付钱 这里不是与C兼容的地方,也是C++最重要的原则之一。

        8
  •  0
  •   McPherrinM    15 年前

    一个未初始化的指针只对一件事有用:给它赋值。你想要一个的唯一原因是你没有一个固定的初始值,但是计划在将来的某个时候分配一个,从而初始化它是一种浪费。如果需要的话,可以将其指定为空或其他值。

    因为在C++中,你可以在一个范围内的任何地方声明变量,而不仅仅是开始,这不再是真正相关的,因为你可以声明它在哪里使用它。

    不过,简短的答案是“否”。只需将其指定为空即可。

        9
  •  0
  •   Michael Krelin - hacker    15 年前

    我不知道你在说什么,但我认为这只会破坏语法兼容性。没有使用未初始化的指针,但是在您知道要放入的值之前,也没有用初始化它,我们不想在它上面浪费时间。

        10
  •  0
  •   Doug T.    15 年前

    假设您有一个函数是一个需要大量指针堆栈变量的中断处理程序:

    void interruptHandler()
    {
        char* ptr0;
        ...
        char* ptrX-1;
        char* ptrX;
    }
    

    假设它是至关重要的,你进出尽可能快。您不想浪费任何不必要的时间初始化为默认值,您知道稍后您将尝试安全地将指针设置为有效的。