从类型为T的数组初始化类型为T*的Stl Vector

Initialise an Stl Vector of type T* from an array of type T

本文关键字:类型 Stl Vector 初始化 数组      更新时间:2023-10-16

如果我有一个数组,如:

struct S {... };
S m_aArr[256];

,我想用它来构造一个向量,如:

std::vector<S*> m_vecS;

是否有办法这样做,而不是循环并推回&m_aArr[i] ?我明白我不能使用传统的方法使用std::beginstd::end上的数组,因为向量是指针之一,原始数组是对象之一,所以我们不能只是传递一块内存。

您可以使用标准库为您执行迭代和推退:

std::transform(std::begin(m_aArr), std::end(m_aArr),
               std::back_inserter(m_vecS), std::addressof<S>);

这将通过对std::addressof<S>函数对m_aArr中的每个元素进行变换。然后,通过std::back_inserter迭代器将转换后的每个元素push_back变换为m_vecS

要在c++ 11之前完成此操作,您将无法访问std::begin, std::endstd::addressof,因此它看起来更像这样:

std::transform(m_aArr, m_aArr + 256, std::back_inserter(m_vecS), boost::addressof<S>);

使用boost::addressof

您可以让std::transform执行循环:

transform(std::begin(a), std::end(a), std::back_inserter(v), 
          [] (S& s) { return &s; });

注意,您不需要完全限定名称std::transform,因为函数名称将由ADL找到。

这是一个完整的程序来测试它的行为:

#include <iostream>
#include <vector>
#include <algorithm> // <== Required for std::transform
#include <iterator>  // <== Required for std::back_inserter, std::begin, std::end
struct S
{
    S() : i(0) { }
    S(int i_) : i(i_) { }
    int i;
};
int main()
{
    S a[256] = { 42 }; // Copy-initializes first element from 42,
                       // default-constructs all other elements
    std::vector<S*> v;
    transform(std::begin(a), std::end(a), std::back_inserter(v), 
              [] (S& s) { return &s; });
    std::cout << v.size() << std::endl; // Prints 256
    std::cout << v[0]->i << std::endl; // Prints 42
    std::cout << v[1]->i << std::endl; // Prints 0
}

这是一个生活例子

使用std::generate_n()执行std::vector的单个分配,而不是通过std::vector::push_back()进行潜在的多个分配的解决方案:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
    struct S {};
    S a[128];
    S* ap = a;
    std::vector<S*> v(sizeof(a)/sizeof(a[0]));
    std::generate_n(std::begin(v), v.size(), [&]() { return ap++; });
    for (size_t i = 0; i < v.size(); i++)
    {
        if (&a[i] != v[i]) // Ensure same address at each element.
        {
            std::cerr << "Errorn";
            break;
        }
    }
    return 0;
}