【问题标题】:Passing std::vector::data to function expecting type** (double pointer)将 std::vector::data 传递给期望类型**(双指针)的函数
【发布时间】:2020-03-26 20:59:00
【问题描述】:

正如标题所描述的,我试图将指向 std::vector 的数据的指针传递给一个需要双指针的函数。以下面的代码为例。我有一个 int 指针d,它作为&d 传递给myfunc1(仍然不确定是否称它为指针的引用或什么),其中函数将其引用更改为填充有@987654326 的int 数组的开头@。但是,如果我有一个 std::vector 的整数并尝试将 &(vec.data()) 传递给 myfunc1,编译器会抛出错误 lvalue required as unary ‘&’ operand。我已经按照this answer 尝试过类似(int *)&(vec.data()) 的方法,但它不起作用。

仅供参考,我知道我可以做类似myfunc2 的事情,我直接将向量作为参考传递,工作就完成了。但我想知道是否可以将myfunc1 与 std::vector 的指针一起使用。

任何帮助将不胜感激。

#include <iostream>
#include <vector>


using std::cout;
using std::endl;
using std::vector;

void myfunc1(int** ptr)
{
    int* values = new int[4];
    // Fill all the with data
    for(auto& i:{0,1,2,3})
    {
        values[i] = i+1;
    }

    *ptr = values;
}

void myfunc2(vector<int> &vec)
{
    int* values = new int[4];
    // Fill all the with data
    for(auto& i:{0,1,2,3})
    {
        values[i] = i+1;
    }

    vec.assign(values,values+4);
    delete values;
}

int main()
{
    // Create int pointer
    int* d;

    // This works. Reference of d pointing to the array
    myfunc1(&d);

    // Print values
    for(auto& i:{0,1,2,3})
    {
        cout << d[i] << " ";
    }
    cout << endl;

    // Creates the vector
    vector<int> vec;

    // This works. Data pointer of std::vector pointing to the array
    myfunc2(vec);

    // Print values
    for (const auto &element : vec) cout << element << " ";
    cout << endl;

    // This does not work
    vector<int> vec2;
    vec2.resize(4);

    myfunc1(&(vec2.data()));

    // Print values
    for (const auto &element : vec2) cout << element << " ";
    cout << endl;

    return 0;
}

编辑: 我的实际代码所做的是从磁盘读取一些二进制文件,并将部分缓冲区加载到向量中。我在从读取函数中获取修改后的向量时遇到了麻烦,这就是我想出的让我解决它的方法。

【问题讨论】:

  • 您无法重新分配std::vector 的底层存储。
  • 打印vector 元素的更好方法:for (const auto &amp;element : vec2) cout &lt;&lt; element &lt;&lt; " ";。您无需创建索引数组并对其进行迭代即可访问向量元素。
  • myfunc1 这样进行手动内存管理的函数与std::vector 根本不兼容。迭代器的存在是为了将整个问题抽象出来。如果一个函数想要将某个范围内的元素设置为某个东西,它可以通过分配给它的输出迭代器来做到这一点。你能告诉我们整个设置应该达到什么目的吗?
  • @MaxLanghof 我的实际代码是读取二进制文件,并将缓冲区的一部分传递给向量。我在从读取文件的函数中获取修改后的向量时遇到了麻烦,而 myfunc2 之类的东西对我有用。

标签: c++ pointers vector reference pass-by-pointer


【解决方案1】:

当你写: myfunc1(&amp;(vec2.data()));

您正在获取右值的地址。指向的int* 是一个临时的,在调用后立即被销毁。

这就是您收到此错误的原因。

但是,正如 @molbdnilo 所说,在您的 myfunc1() 函数中,您正在重新分配指针(顺便说一下不关心破坏先前分配的内存)。 但是std::vector 已经自行管理其数据存储器。你不能也不能把手放在上面。


我的实际代码所做的是从磁盘读取一些二进制文件,并将部分缓冲区加载到向量中。

一种解决方案可能是通过将迭代器传递到开头并将迭代器传递到所需部分的末尾以提取构造函数的参数来构造您的std::vector

例如:

int * buffer = readAll("path/to/my/file"); // Let's assume the readAll() function exists for this example

// If you want to extract from element 5 to element 9 of the buffer
std::vector<int> vec(buffer+5, buffer+9);

如果std::vector 已经存在,您可以像在myfunc2() 中那样使用assign() 成员函数:

vec.assign(buffer+5, buffer+9);

当然,在这两种情况下,您都必须确保在访问缓冲区时没有尝试访问越界元素。

【讨论】:

    【解决方案2】:

    问题是您不能获取data() 的地址,因为它只是指针的临时副本,因此写入指向它的指针没有多大意义。这很好。您不想将data() 传递给此函数,因为它会用新数组覆盖指针,并且会破坏向量。您可以从函数中删除一个 * 并只分配给它而不在那里分配内存。这将起作用,但请确保在调用者中分配内存(使用resize,仅reserve 将导致未定义的行为,因为data() 只是指向有效范围[data(), data() + size()) 开头的指针。范围[data(), data() + capacity ()) 不一定有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-06
      相关资源
      最近更新 更多