pf.string()
输出似乎有一些奇怪的行为,其中pf
是使用p.filename()
生成的,其中p
的类型为boost::filesystem::path
,并使用 char const * 或 std :: string 。
以下是代码段:
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main(int argc, char **argv) {
fs::path p(argv[0]); // or fs::path p((std::string(argv[0])));
fs::path &&pf = p.filename(); // or fs::path pf = p.filename();
std::string const &name = p.filename().string();
std::cout << "*" << name << "*\n";
std::string const &p_name = pf.string();
std::cout << "*" << p_name << "*\t";
std::cout << "*" << name << "*\n";
std::string s_name = p.filename().string();
std::cout << "*" << s_name << "*\t";
std::cout << "*" << name << "*\n";
return 0;
}
这里的argv[0]
是fs.out
,可执行文件的输出(使用clang3.4
/ gcc4.9
和-O3
/ -O0
编译)是:
**
*fs.out* **
*fs.out* *fs.out*
我使用的提升版本 1.55 来自 Debian jessie(测试)包。
我的问题:
name
为空?p_name
不为空,但第2行name
为空?s_name
和name
之间没有关系?答案 0 :(得分:4)
你正在参考临时工。
Iff绑定到const
引用(如p_name
),临时的生命周期将扩展到包含范围的末尾。
否则您只是调用未定义的行为。这也解释了当您分配给完全不同的变量时name
如何变化。这显然是因为s_name
发生来分配name
仍然(错误地!)所引用的相同内存块。可能会发生更糟糕的事情。
您应该按值filename()
(以及朋友)的返回值(如果类型支持,则应该在现代编译器上自动表现为 move 。)
注意 MSVC“出现”接受此代码并“按照您的意愿行事” - 大概是因为它有一个非标准扩展,即使在绑定时也可以延长临时生命周期非const引用。
答案 1 :(得分:3)
name
是参考。即,只有将引用到p.filename().string()
。但是,这是一个临时,即在语句完成后它会被销毁,让name
引用无效的内存。你处于未定义的行为国家,幸运的是你的程序没有崩溃。
(关于你的第二个问题,const &
上的细则更新了我,所以给他+1。)
在第三轮中,s_name
是对象,即它拥有p.filename().string()
的副本(因此有效)。幸运的是,编译器显然在name
引用的相同位置创建了该对象...
毋庸置疑,你不应该依赖这种行为。