从向量<string>到 char** 的转换仅携带第一个元素

Conversion from vector<string> to char** only carries the first element

本文关键字:转换 元素 第一个 char lt 向量 string gt      更新时间:2023-10-16

我已经用我的问题对下面的代码进行了大量注释。基本上,问题是我试图通过std::vector<std::string>伪造argv,但我从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.

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 返回:如果pos < size(),则*(begin() + pos)否则引用值为 charT()T 类型的对象; 引用的值不得修改。

(严格来说,这并不是说*(&str.operator()(str.size()-1)+1)charT()的,而是NULL 必须存储在实际的数据缓冲区中,以便实现遵守字符串的常量访问保证。

所以完全没有必要诉诸存储str.c_str()的结果,尽管这是一个有效的替代方法。

而且,由于向量默认初始化其成员,因此argv本身也是以 null 结尾的。

因此,您的矢量没有问题;当我抽象出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

(现场演示(

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

试试这个:

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

glutInit采用int *作为第一个参数,而不是int

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