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

问题描述 投票:0回答:1

我想表示一个包含几个整数的结构的std::vector作为整数的“展平”向量,而不复制数据。

我用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>>
c++ vector std allocator reinterpret-cast
1个回答
2
投票

您无法合法地将整个矢量重新解释为不同类型的矢量。但是,您可以合法地将指向struct的指针强制转换为指向该结构的第一个元素的指针。这样可行:

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*
© www.soinside.com 2019 - 2024. All rights reserved.