C++ 关于临时表销毁的编译器策略

C++ 关于临时表销毁的编译器策略,c++,visual-studio-2008,compiler-construction,intel,C++,Visual Studio 2008,Compiler Construction,Intel,我一直在玩下面的代码file\u string返回一个临时字符串,该字符串在语句结束前应仅“活动”。在VisualStudio2008中,当您使用pTempFolder时,它会像预期的那样包含垃圾。但在Linux中,使用英特尔编译器11.0,pTempFolder仍然指向有效字符串。编译器在销毁临时文件方面是否有不同的策略,有点急切(视觉)还是懒惰(英特尔)?或者这只是巧合 boost::filesystem wpathTempFolder("/tmp"); const wchar_t* con

我一直在玩下面的代码
file\u string
返回一个临时字符串,该字符串在语句结束前应仅“活动”。在VisualStudio2008中,当您使用
pTempFolder
时,它会像预期的那样包含垃圾。但在Linux中,使用英特尔编译器11.0,
pTempFolder
仍然指向有效字符串。编译器在销毁临时文件方面是否有不同的策略,有点急切(视觉)还是懒惰(英特尔)?或者这只是巧合

boost::filesystem wpathTempFolder("/tmp");
const wchar_t* const pTempFolder = wpathTempFolder.file_string().c_str();
// use pTempFolder
顺便说一句,这是boost文件系统版本2。我还看到boost文件系统版本3中的
文件\u string
被弃用。还有一个新的
c_str
方法,它对字符串&,而不是临时字符串进行操作

/*filesystem 2*/
const string_type file_string() const;
/*filesystem 3*/
const string_type&  native() const;  // native format, encoding
const value_type*   c_str() const;   // native().c_str()

很可能,字符串仍然无效,只是碰巧该部分内存尚未在操作系统级别取消分配,并且“碰巧”正常工作。该程序表现出未定义的行为,其中始终包括“可能会继续工作,就好像没有出现任何问题”。VisualStudio在这里完全正确地使您的程序崩溃或几乎任何事情

临时文件的生存期(除少数例外)为 完整表达式的结尾。指向的数组对象的生存期 通过
std::string::c_str()的返回值,
不超过 字符串对象本身的长度(如果有,可能更短) 对字符串调用非常量函数)。访问 对象在其生存期结束后是未定义的行为,因此
您无法从编译器的工作中得出任何结论。

只是一个nit,但应该“取消分配或覆盖”。在数据的生命周期结束后访问数据是一种未定义的行为,因此任何事情都可能发生。@James:如果数据没有被覆盖,他不会得到垃圾,他会得到一个非常好的字符串。如果内存实际返回到操作系统,他在试图访问它时可能会崩溃。(不是真正的崩溃,但Purify或Valgrind也会抱怨。即使读取的数据看起来是正确的。)@James,如果内存所在的页面实际上是由操作系统释放的,那么实际的崩溃是可能的。然后,即使读取也会导致无效访问(linux上的segfault)。虽然我认为linux上的普通堆内存实际上从未返回到内核,但在windows上,我认为malloc确实是基于页面分配的,因此它更可能在windows.Clear上崩溃。我想知道我在Linux中的行为是否不仅仅是巧合,是否有些编译器会将堆栈临时性的销毁延迟到函数结束。我想这根本没有什么意义。现在对“少数例外”感到好奇。@rturrando有一些“单例”的角色涉及清理——我使用单例来管理临时文件,例如,在程序结束时删除(或不删除)它们。这样的单例不能在析构函数中使用(因为它们可能不存在),但也很有用(如果您需要在析构函数中创建临时文件,那么您在析构函数中做的太多了)。为什么不在
main
的堆栈上分配这样的对象呢?没有必要求助于单例。@DeadMG我不确定我们在谈论哪些对象。不知何故,这里出现了一些与另一个线程相关的注释。但是,如果是单体问题,C++中使用单体的通常原因是因为静态对象的构造函数可能需要它。C++中常用的单体习惯用法比其他任何方法更经常地用来解决初始化问题的顺序。