将c-array赋值给c++ vector

Assigning c-array to c++ vector

本文关键字:c++ vector 赋值 c-array      更新时间:2023-10-16

我有一个关于onstack创建的数组的生命周期以及将它们转换为c++向量的问题。例如,我有两个函数:

void getVector()
{ 
    auto myVector = createVectorFromArray();
}
vector<float> createVectorFromArray()
{
    float myArr[10];
    readDataFromSomewhere(myArr, 10); //some read data function with signature void(float*, size_t)
    vector<float> resVector;
    resVector.assign(myArr, myArr+10);
    return resVector;
}

据我所知,数组myArr将在我们离开函数createVectorFromArray时被杀死。因此,函数getVector中vector myVector的迭代器将不指向任何地方。我说的对吗,还是有另一种方式?在这种情况下,我应该如何更好地从数组中生成向量来从函数中返回它呢?

谢谢!

你可以这样重写createVectorFromArray,这样你就不会再为vector赋值数组了:

vector<float> createVectorFromArray()
{
    vector<float> resVector(10);
    readDataFromSomewhere(&resVector[0], resVector.size());
    return resVector;
}

std::vector是连续内存容器,因此您可以使用它作为普通旧C函数的接口

这个答案旨在讨论各种方法,解释它们,并将它们置于上下文中。

选项1:原生到矢量拷贝:

vector<float> createVectorFromArray()
{
    // data copied once
    float myArr[10];
    readDataFromSomewhere(myArr, 10);
    // vectors are lightweight handles. zero-cost construction
    // since the optimiser will see that the next statement assigns to
    // the vector
    vector<float> resVector;
    //
    // data copied twice
    //
    resVector.assign(myArr, myArr+10);
    //
    // it's almost guaranteed that RVO will elide this copy. As of c++17
    // it's a guarantee. Returning the vector is fine
    return resVector;
}

问题:

  1. 数据复制两次
  2. vector将需要内存分配

选项2:直接使用vector

vector<float> createVectorFromArray()
{
    // Will allocate space and
    // default-initialise the floats (i.e. they won't be initialised)
    vector<float> resVector(10);
    //
    // one data copy. perfectly safe and idiomatic.
    // std::addressof expressed intent clearly.
    //
    readDataFromSomewhere(std::addressof(resVector[0]), resVector.size());
    //
    // it's almost guaranteed that RVO will elide this copy. As of c++17
    // it's a guarantee. Returning the vector is efficient.
    return resVector;
}

问题:

  1. vector将需要内存分配

更好……

选项3:重用现有的vector

void createVectorFromArray(vector<float>& resVector)
{
    //
    // if resVector has been used before and has a capacity() of 10
    // or more, no memory allocation necessary
    //
    resVector.resize(10);
    // one copy of data
    readDataFromSomewhere(std::addressof(resVector[0]), resVector.size());
}

问题:

  1. 可能不太容易使用参考接口。

我该如何在选项2和3之间做出选择?

选项2更具可读性(恕我直言),但如果在循环中使用,成本会很高。所以如果是一次性的,我会选择这个

如果我在循环中将数据读入缓冲区,我可能希望避免不必要的内存分配。因此,重用vector的容量将是一个明智的举动。

std::vector<float> buf;
while (thereIsMoreData())
{
    createVectorFromArray(buf);   // option 3
    useTheData(buf);
    // data no longer needed, so we can re-use the vector
}

选择:

while (thereIsMoreData())
{
    // the passing of the vector is efficient, particularly as of c++11
    // however, we still suffer one memory allocation per loop.
    // probably undesirable in a high performance environment.
    useTheData(createVectorFromArray());   // option 2
}

最后……

选项4:

提供。允许用户按照他/她的意愿使用高性能方法或"可读"方法

void createVectorFromArray(vector<float>& resVector)
{
    //
    // if resVector has been used before and has a capacity() of 10
    // or more, no memory allocation necessary
    //
    resVector.resize(10);
    // one copy of data
    readDataFromSomewhere(std::addressof(resVector[0]), resVector.size());
}
// overload
std::vector<float> createVectorFromArray()
{
    std::vector<float> result;
    createVectorFromArray(result);
    return result;
}