c++ - boost::filesystem::path::string() 输出的奇怪行为

标签 c++ string boost

pf.string() 输出似乎有一些奇怪的行为,其中 pf 是用 p.filename() 生成的,其中 pboost::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*

我使用的 boost 版本是 1.55 来自 Debian jessie(testing) 包。

我的问题:

  • 为什么 name 的前两行是空的?
  • 为什么 p_name 不为空而 name 在第 2 行为空?
  • 为什么这个程序在第 3 行有正确的(?)输出,尽管 s_namename 之间似乎没有关系?

最佳答案

您正在引用临时对象。

如果绑定(bind)到 const 引用(如 p_name),临时对象的生命周期将延长到包含范围的末尾。

否则,您只是在调用未定义的行为。这也解释了当您分配给一个完全不同的变量时 name 是如何变化的。这显然是因为 s_name 碰巧 分配了 name 仍然(错误地!)引用的相同内存块。可能会发生更糟糕的事情。

您应该按值获取 filename()(和 friend )的返回值(如果类型支持的话,在现代编译器上应该自动表现为 move) .

注意 MSVC 确实“似乎”接受此代码并“做你期望的事”——大概是因为它有一个非标准的扩展,即使在绑定(bind)时也允许延长临时对象的生命周期到非常量引用。

关于c++ - boost::filesystem::path::string() 输出的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25788116/

相关文章:

c++ - 打包结构/避免填充

c++ - QT函数模板

java - 使用二进制编码将 byte[] 转换为 String

c++ - 对重载函数的模糊调用 - std::to_string

c++ - 有没有比 allocator_type 更好的方法来区分可调整大小的容器?

c++ - boost shared_ptr 和 'this'

c++ - Boost Spirit Qi - 用两个组件序列解析列表

c++ - 如何在编译时获取指向非静态数据成员的指针的对象类型?

c++ - 为什么 Eigen 在下面的例子中比 ublas 慢 5 倍?

linux - std::string::assign() method from libstdc++.so.6中奇怪的SIGSEGV段错误