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初始化指针?")导致海报提出这个问题.
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)
即使它具有所有函数的完整定义,编译器也很难分析这个.
初始化指针需要一些时间.大多数时候你不应该关心这一点,但在极少数情况下它会产生影响.C(以及扩展C++)的指导原则之一是永远不会让你付出你可能不需要的东西.不要为你不使用的东西买单.
另一种罕见的情况可能出现在嵌入式编程中,其中变量对应于硬件寄存器.在寄存器中放置一个值将启动硬件执行某些可能不合适的操作.
小智 6
用于单位指针?请参见std :: strtol().
char * bad;
long n = std::strtol( "123xyz", &bad, 10 );
Run Code Online (Sandbox Code Playgroud)
在此调用之后,bad将包含指向'x'的指针.初始化是没有意义的.