push_back() 的奇怪行为 filesystem::path 的 .string().data() 结果变成了 "vector<const char *>"
Weird behavior of push_back() a filesystem::path's .string().data() result into a "vector<const char *>"
运行这个节目
#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 的第一个元素不是 "a.o"?
我尝试在 A 行中断,发现当 "b.o" 是 push_back() 到 argv 时,argv 的第一个元素 更改为 从"a.o" 到 "b.o".
然后,当我将 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() 之间的区别?
问题是 the path::string()
function returns 字符串 by value.
一旦表达式 p.string().data()
结束,该值将被 破坏。
这意味着指针将立即变为无效,当您尝试取消引用它时(例如打印时),您将得到 undefined behavior。
显而易见的解决方案是不使用 char*
的向量作为字符串,而是使用 std::string
的向量。
至于使用p.string().data()
(或p.string().c_str()
)和p.c_str()
的区别,就是p.c_str()
returns内部字符串的指针p
引用的 path
对象。该 path
对象将不会被破坏,直到您 clear
向量或向量(及其包含的对象)的生命周期结束(当向量被破坏时)。
请注意,如果您使用了
这样的循环
for (auto p : paths) { ... }
其中 p
是 path
对象的副本,那么即使使用 p.c_str()
也会遇到同样的问题,因为对象 p
将结束其life 并在循环的每次迭代结束时被破坏。
运行这个节目
#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 的第一个元素不是 "a.o"?
我尝试在 A 行中断,发现当 "b.o" 是 push_back() 到 argv 时,argv 的第一个元素 更改为 从"a.o" 到 "b.o".
然后,当我将 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() 之间的区别?
问题是 the path::string()
function returns 字符串 by value.
一旦表达式 p.string().data()
结束,该值将被 破坏。
这意味着指针将立即变为无效,当您尝试取消引用它时(例如打印时),您将得到 undefined behavior。
显而易见的解决方案是不使用 char*
的向量作为字符串,而是使用 std::string
的向量。
至于使用p.string().data()
(或p.string().c_str()
)和p.c_str()
的区别,就是p.c_str()
returns内部字符串的指针p
引用的 path
对象。该 path
对象将不会被破坏,直到您 clear
向量或向量(及其包含的对象)的生命周期结束(当向量被破坏时)。
请注意,如果您使用了
这样的循环for (auto p : paths) { ... }
其中 p
是 path
对象的副本,那么即使使用 p.c_str()
也会遇到同样的问题,因为对象 p
将结束其life 并在循环的每次迭代结束时被破坏。