reinterpret_cast 如何展平 std::vector?

How reinterpret_cast works for flattening a std::vector?

我想将包含多个整数的结构的 std::vector 表示为 "flatten" 整数向量, 无需复制数据

我尝试了一些带有 reinterpret_cast 的东西,如下所示:

#include <vector>
#include <iostream>

struct Tuple
{
    int a, b, c;
};

int main()
{
    // init
    std::vector<Tuple> vec1(5);
    for(size_t i=0; i<vec1.size(); ++i)
    {
        vec1[i].a = 3 * i + 0;
        vec1[i].b = 3 * i + 1;
        vec1[i].c = 3 * i + 2;
    }   

    // flattening
    std::vector<int>* vec2 = reinterpret_cast<std::vector<int>*>(&vec1);

    // print
    std::cout << "vec1 (" << vec1.size() << ")  : ";
    for(size_t i=0; i<vec1.size(); ++i)
    {
        std::cout << vec1.at(i).a << " " << vec1.at(i).b << " " << vec1.at(i).c << " ";
    }
    std::cout << std::endl;

    std::cout << "vec2 (" << vec2->size() << ") : ";
    for (size_t j = 0; j < vec2->size(); ++j)
    {
        std::cout << vec2->at(j) << " ";
    }
    std::cout << std::endl;

    return 0;
}

效果很好,因为输出是:

vec1 (5)  : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
vec2 (15) : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 

我的问题是:

您不能合法地将整个向量 reinterpret_cast 转换为不同类型的向量。但是您可以合法地将指向结构的指针转换为指向该结构的第一个元素的指针。所以这有效:

std::vector<Tuple> vec1(5);
int* vec2 = &vec1.front().a;
size_t vec2_size = vec1.size() * sizeof(vec1[0]) / sizeof(vec2[0]);

for (size_t j = 0; j < vec2_size; ++j)
{
    std::cout << vec2[j] << " ";
}

您需要确保 Tuple 中没有填充,所以:

static_assert(sizeof(Tuple) == 3 * sizeof(int), "Tuple must be 3 ints");

回答您的项目符号问题:

  • 此行为是否依赖于编译器?
    • 您的代码不合法​​。
  • vec2 怎么知道向量的大小是 15 而不是 5?
    • 你很幸运,你的代码是非法的。
  • 他们是否有任何其他解决方案避免使用 reinterpret_cast?
    • 见上文。
  • 如果 vec1 有一个特定的分配器:std::vector>,那么 vec2 的类型应该是什么?
    • 同上,int*.