在C或C++中是否有未初始化指针的用途?

Joh*_*ohn 4 c c++ compatibility pointers initialization

这个问题的一个评论中,提出默认情况下初始化C++指针会破坏与C的兼容性.

那没关系,但为什么会这样呢?我认为唯一真正重要的是因为某些原因我想要一个未初始化的指针.但我想不出有什么理由让我想拥有它.

是否有未初始化指针的用途?或兼容性问题只是兼容行为之一(即不增加开销)而不是破坏代码之一?

Adi*_*sak 17

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

基本上我们会在PC电饭煲中创建控制台端(Playstation)对象.然后,为了减少碎片过载,我们将数据对象打包在一个具有单个alloc的连续缓冲区中.然后将对此缓冲区中的数据对象的引用进行更改,以从指向偏移量的指针中减去基数(取消修复调用 - 我们还有一个虚拟修复/取消修复调用,它接受缓冲区基础并可以在偏移量和指针之间进行转换).

当我们加载数据时,它加载到一个大块中.根引用的所有数据都不在根对象中.我们可以在根上执行一个就地"new",它将为对象初始化正确的VF表并修复所有附加的块(通过分别执行new new然后修复附加的块).

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


FWIW,这是视频游戏世界的常用技术.这篇Gamasutra文章(不是我或我的同事写的)详细解释了他们在另一家公司所做的类似事情:

此外,这个关于SourceForge的讨论主题.

甚至还有几个关于这个主题的GDC(游戏开发者大会)会谈.

在Google上搜索"就地加载"将提供许多使用此技术的人的其他示例,这些示例基本上需要未初始化的指针.


注意:目前,这是实际回答问题的唯一响应("C或C++中是否有未初始化指针的使用?")通过对必须保持单元化的指针进行特定用途.

所有其他响应都是引用原始问题的更好答案("[C++]为什么默认情况下没有用NULL初始化指针?")导致海报提出这个问题.

  • 是的,我愿意.我们在PS和XBOX的特定情况下使用它.问题是否有理由做某事.我们这样做是因为它使我们的游戏加载需要几秒而不是几分钟(大块单块加载而不是创建和加载的许多小对象).它还节省了大量的内存和碎片.在视频游戏世界(以及一般的嵌入式系统)中,这些类型的黑客通常是达到性能和内存目标所必需的. (10认同)

Pav*_*aev 11

首先,默认情况下初始化指针(或任何其他变量)不会破坏与C的兼容性.C和C++都声明未初始化变量的值是不确定的; 在实践中,这意味着它可以保存任何值(包括陷阱表示),但请注意0属于"任何值"的集合!因此,一致的实现可以很好地初始化所有指针0.但是,如果你的程序依赖于它,则不符合要求.

现在,为什么你可能希望你的指针不被初始化:主要是在它被写入之后.例如:

void foo(int*& p) {
   p = new int;
}

int* p; // why initialize? we overwrite it anyway
foo(p);
Run Code Online (Sandbox Code Playgroud)

你可以说编译器应该能够优化它.不幸的是,如果定义foo不可用(例如禁用全局链接时优化;或者它们已启用,但函数在DLL中),则不能这样做,因为它不知道是否foo会尝试读取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
   ...
}
Run Code Online (Sandbox Code Playgroud)

即使它具有所有函数的完整定义,编译器也很难分析这个.


Mar*_*som 8

初始化指针需要一些时间.大多数时候你不应该关心这一点,但在极少数情况下它会产生影响.C(以及扩展C++)的指导原则之一是永远不会让你付出你可能不需要的东西.不要为你不使用的东西买单.

另一种罕见的情况可能出现在嵌入式编程中,其中变量对应于硬件寄存器.在寄存器中放置一个值将启动硬件执行某些可能不合适的操作.


小智 6

用于单位指针?请参见std :: strtol().

char * bad;
long n = std::strtol( "123xyz", &bad, 10 );
Run Code Online (Sandbox Code Playgroud)

在此调用之后,bad将包含指向'x'的指针.初始化是没有意义的.