从字符串文字初始化 char* 向量的好方法是什么?

问题描述 投票:0回答:2

直到 C++11,人们可以编写以下内容:

#include <vector>
using namespace std;

int main_under_test(int argc, char* argv[]) {
    return 0;
}

int main() {
    vector<char*> args {"--foo", "--bar"};

    return main_under_test(args.size(), args.data());
}

但是,将文字值分配给非

const
char*
不再可能了。

幸运的是,从 C++11 开始,我们保证

std::string::data()
是空终止的,因此我们可以执行以下操作:

#include <string>
#include <vector>
using namespace std;

int main_under_test(int argc, char* argv[]) {
    return 0;
}

int main() {
    vector<string> strArgs {"--foo", "--bar"};
    vector<char*> args;
    for (auto & strArg : strArgs) {
        args.push_back(strArg.data());
    }

    return main_under_test(args.size(), args.data());
}

然而,虽然这有效,但看起来不太好。有没有更好的方法从文字初始化非

vector
const
char*
(或数组)?

c++ string char literals
2个回答
2
投票

在 C++23 中:

std::vector<std::string> strings = {"--foo", "--bar"};
auto ptrs = strings
    | std::views::transform([](auto &s){return s.data();})
    | std::ranges::to<std::vector>();

Libstdc++ 还没有

ranges::to
,但这适用于 libc++ 和 MSVC STL。

遗憾的是,我们无法将

&std::string::data
直接传递给
transform
,因为
data()
已超载。


0
投票

假设

main_under_test
将来会取代当前的
main
函数,那么对我来说,简单地使用 shell 脚本 (linux) 或批处理文件 (windows) 似乎更合适 – 您可以在其中动态修改参数无需重新编译(!) - 现在只需将
main_under_test
函数设置为真正的
main
函数即可(所以实际上是 XY 问题…)。

如果您坚持当前的方法,那么您可以使用它们来初始化数组,而不是创建指向字符串文字的指针:

char raw[][128] = { "--foo", "--bar" };

好的,现在我们有了一个 2D 数组 - 并且它不能仅仅转换为指针数组,因此在这种情况下我们需要自己在代码中执行此操作,但只需编写一次:

int main(int argc, char* argv[])
{
    char raw[][128] = { "--foo", "--bar" }; // arbitrarily modifiable...

    char* args[std::size(raw) + 2] = { *argv }; // the executable name (!)
    char** a = args;
    for(auto& r : raw)
    {
        *++a = r;
    }
    *++a = nullptr; // argv is always null-terminated as well!

    return main_under_test(std::size(args) + 1, args);
}

godbolt演示。

另一种选择是简单地抛弃 const-ness (

{ const_cast<char*>("literals") }
),但随后你依赖于
main_under_test
严格承诺不修改参数,否则会产生未定义的行为,因此这种方法不太值得推荐。

© www.soinside.com 2019 - 2024. All rights reserved.