reinterpret_cast如何用于展平std :: vector?

时间:2019-02-22 23:53:50

标签: c++ vector std allocator reinterpret-cast

我想表示一个包含几个整数的结构的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 

我的问题是:

  • 此行为是否与编译器相关? (我正在使用g++ 6.3.0
  • vec2如何知道向量的大小是15而不是5
  • 他们是否有其他解决方案避免使用reinterpret_cast? (如果我“偶然地” double添加了一个Tuple成员,则可能很难跟踪所产生的问题...)
  • 如果vec1具有特定的分配器:std::vector<Tuple,A<Tuple>>,则vec2的类型应该是什么? std::vector<int>std::vector<int,A<int>>std::vector<int,A<Tuple>>

1 个答案:

答案 0 :(得分:2)

您不能合法地将整个载体重新解释_转换为另一种载体。但是您可以合法地将结构的指针转换为该结构的第一个元素的指针。如此有效:

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*相同。