",c++,string,vector,char,std-filesystem"/>

首页 > 解决方案 > push_back() a filesystem::path 的 .string().data() 的奇怪行为导致“向量"

问题描述

运行这个程序

#include <iostream>
#include <filesystem>
#include <vector>

using namespace std;
namespace fs = filesystem;

int main() {
    vector<fs::path> paths{"a.o", "b.o"};

    vector<const char *> argv{};
    for (auto &p : paths) {
        argv.push_back(p.string().data()); // line A
    }
    argv.push_back(paths[0].string().data());
    argv.push_back(paths[1].string().data());

    for (auto &s : argv) {
        cout << s << endl;
    }

    return 0;
}

得到

b.o
b.o
a.o
b.o

为什么 argv 的第一个元素不是“ao”?

我尝试在 A 行中断,发现当“bo”是 push_back() 进入 argv 时,argv 的第一个元素从“ao”变为“bo”

然后,当我将 A 行更改为

        argv.push_back(p.string().c_str()); // line A: .string().data() -> .string().c_str()

结果相同。

当我将 A 行更改为

        argv.push_back(p.c_str()); // line A: .string().data() -> .c_str()

突然我得到了预期的结果:

a.o
b.o
a.o
b.o

有人可以解释奇怪的行为以及 .string().data() 和 .c_str() 之间的区别吗?

标签: c++stringvectorcharstd-filesystem

解决方案


问题是path::string()函数按值返回字符串。

表达式结束后立即销毁的值。p.string().data()

这意味着指针将立即变得无效,并且当您尝试取消引用它时(例如打印它时) ,您将有未定义的行为。

显而易见的解决方案是不使用向量的char*字符串,而是使用向量std::string


至于 using p.string().data()(or p.string().c_str()) 和之间的区别p.c_str(),它是返回一个指针,指向由 .引用p.c_str()的对象内部的内部字符串。在向量或向量(及其包含的对象)的生命周期结束(当向量被破坏时)之前,该对象不会被破坏。pathppathclear

请注意,如果您使用循环,例如

for (auto p : paths) { ... }

whereppath对象的副本,那么即使使用 ,您也会遇到同样的问题p.c_str(),因为对象p将结束其生命并在循环的每次迭代结束时被破坏。


推荐阅读