从vector <string>到char**的转换仅包含第一个元素

Sep*_*ehr 0 c++ c++11

我用我的问题大量评论了下面的代码.基本上问题是我试图假装argv,std::vector<std::string>但我从Visual Studio得到一个我不期望的行为.你能详细说明我在这里缺少什么吗?

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.
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 5

tl; dr你的来电glutInit是错的.见下文.


尽管许多其他贡献者声称,你的单个C字符串完全是NULL终止,因为在C++ 11(你正在使用)中,保证str.operator[](str.size())评估为null字符:

[C++11: 21.4.5]:

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

1要求:pos <= size().
2返回:*(begin() + pos)if pos < size(),否则引用T具有值的类型的对象charT() ; 参考值不得修改.

(严格地说,这并没有说明*(&str.operator()(str.size()-1)+1)就是charT(),但NULL 必须存储在实际的数据缓冲区,以通过字符串的恒定时间访问保证遵守的实现.)

因此,根本不需要存储结果str.c_str(),尽管这是一种有效的替代方法.

并且,由于向量默认初始化其成员,因此您argv自己也是以空值终止的.

因此,你的载体没有问题 ; 当我抽象出OpenGL时,我无法重现你的问题:

#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
Run Code Online (Sandbox Code Playgroud)

(现场演示)

但是,glutInit需要指向数据缓冲区大小的指针,而不是大小本身.所以,当你过世时argv.size(),那是错的.

试试这个:

int argv_size = argv.size();
glutInit(&argv_size, argv.data());
Run Code Online (Sandbox Code Playgroud)