C++ 从矢量转换<;字符串>;to char**只携带第一个元素

C++ 从矢量转换<;字符串>;to char**只携带第一个元素,c++,c++11,C++,C++11,我已经用我的问题对下面的代码进行了大量的注释。基本上,问题是我试图通过一个std::vector来伪造argv,但是我从VisualStudio得到了一个我不期望的行为。请你详细说明我在这里遗漏了什么 std::vector<std::string> argv_storage; for (std::size_t i = 0; i < 10; ++i) { // I copy output of generate_rand_str() because I will nee

我已经用我的问题对下面的代码进行了大量的注释。基本上,问题是我试图通过一个
std::vector
来伪造
argv
,但是我从VisualStudio得到了一个我不期望的行为。请你详细说明我在这里遗漏了什么

std::vector<std::string> argv_storage;
for (std::size_t i = 0; i < 10; ++i)
{
    // I copy output of generate_rand_str() because I will need it
    // later in the code.
    argv_storage.push_back( std::string( generate_rand_str() ) );
}

std::vector<char *> argv( argv_storage.size() + 1 );    // one extra for NULL
for (std::size_t i = 0; i != argv_storage.size(); ++i)
{
    argv[i] = &argv_storage[i][0];
}

// Here if I access elements like argv.data()[index]
// they are perfectly fine but when I do:

char** test = argv.data();
// Visual Studio debugger only shows argv.data()[0]

// I want to pass this to glutInit() ...
int argc = argv.size() - 1; // one less for the NULL
glutInit(&argc, argv.data());

// Inspection of arguments passed to glutInit() also shows that ONLY the
// the first element of argv is passed.
std::向量argv_存储;
对于(标准::尺寸i=0;i<10;++i)
{
//我复制generate_rand_str()的输出,因为我需要它
//代码的后面部分。
argv_storage.push_back(std::string(generate_rand_str());
}
std::vector argv(argv_storage.size()+1);//空值另加一个
对于(std::size_t i=0;i!=argv_storage.size();++i)
{
argv[i]=&argv_存储[i][0];
}
//如果我访问argv.data()[index]之类的元素
//它们非常好,但当我这样做时:
字符**测试=argv.data();
//Visual Studio调试器仅显示argv.data()[0]
//我想把这个传递给glutInit()。。。
int argc=argv.size()-1;//空值少一个
glutInit(&argc,argv.data());
//对传递给glutInit()的参数的检查还显示,只有
//传递argv的第一个元素。

tl;dr您对
glutInit
的调用是错误的。见下文


尽管许多其他贡献者声称,您的单个C字符串完全以NULL结尾,因为在C++11(您正在使用的)中,
str.operator[](str.size())
可以保证计算为NULL字符:

[C++11:21.4.5]:

const_参考运算符[](size_type pos)const
参考运算符[](大小\类型pos)


1要求:
pos
glutInit
int*
作为第一个参数,而不是
int


你的向量/字符串看起来很凌乱,但很正确

“因此,根本不需要存储str.c_str()的结果(无论如何,只要在str上调用非常量成员,它就会变得不安全)。”在我看来,获取指针
&str[0]
不再安全,因为调用非常量成员可能会触发重新分配,然后获取的指针就变得无效。我仍然更喜欢
data()
c_str()
(它们在c++11中做同样的事情)而不是将指针指向字符串的第一个元素,因为这是从字符串对象获取c样式字符串的有文档记录的方法,并且至少可以保证在第一段末尾,你是说空字符吗?@cdhowie:这很公平。@JasonR:是的,我有。。。指针将无效。我不确定指针
&str[0]
何时无效是否有严格的保证。(虽然我怀疑一个健全的实现会从
data()
c_str()
返回
&str[0]
,但这也不能保证。)最终可能是一样的,所以。。。shrugI实际上传递了一个
int*
(上面的代码中没有显示),但是您对
glutInit
的评论非常有意义,因为glut修改了argv和argc,因此一切都变得混乱。你有没有一个解决方案是防过剩的?@3p3r:为什么不给我们看看你的实际代码?然后我们可以帮你诊断。而不是为您生成一个新程序。@LightnessRacesinOrbit我更新了它,就是这样。我所有的代码都是这样的,generate_rand_str()实际上是不相关的,因为它来自Lua端,我可以在那里有一个随机字符串生成算法,它与我想要做的没有任何区别。另外,我正在复制它的输出。它返回
char*
@3p3r:那么我还是不明白你在问什么。我们已经证明您的代码是正确的。你要求我们告诉你你遗漏了什么,但你没有遗漏任何东西,也没有显示任何相反的证据!
#include <vector>
#include <string>
#include <iostream>

int main()
{
    std::vector<std::string> argv_storage;
    for (std::size_t i = 0; i < 10; ++i)
    {
        // I copy output of generate_rand_str() because I will need it
        // later in the code.
        argv_storage.push_back(std::to_string(i));
    }

    std::vector<char *> argv( argv_storage.size() + 1 );    // one extra for NULL
    for (std::size_t i = 0; i != argv_storage.size(); ++i)
    {
        argv[i] = &argv_storage[i][0];
    }

    char** test = argv.data();
    while (*test != NULL) {
        std::cout << *(test++) << ' ';
    }
}

// 0 1 2 3 4 5 6 7 8 9
int argv_size = argv.size();
glutInit(&argv_size, argv.data());