从vector <string>到char **的转换只带有第一个元素</string>

时间:2014-12-18 17:03:23

标签: 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.

2 个答案:

答案 0 :(得分:5)

tl; dr 您对glutInit的来电是错误的。见下文。


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

  

[C++11: 21.4.5]:

     

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

     

1 需要:pos <= size().
   2 返回:*(begin() + pos)如果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

live demo

但是,glutInit期望指针指向数据缓冲区大小,而不是大小本身。因此,当您通过argv.size()时,那是错误的。

试试这个:

int argv_size = argv.size();
glutInit(&argv_size, argv.data());

答案 1 :(得分:2)

glutInitint *作为第一个参数,而不是int

你的矢量/字符串看起来很乱但是正确。