C++ 如何将void*强制转换回std::vector<;浮动>;

C++ 如何将void*强制转换回std::vector<;浮动>;,c++,stl,casting,C++,Stl,Casting,如果我知道vf的大小,我可以从vvp.at(0)在第19行构建数据 #include <iostream> #include <vector> typedef void* VoidPointer; typedef std::vector< float > VF; typedef std::vector< VoidPointer > VVP; int main(int argc, char** argv) { VF vf; vf.

如果我知道
vf
的大小,我可以从
vvp.at(0)
在第19行构建
数据

#include <iostream>
#include <vector>

typedef void* VoidPointer;
typedef std::vector< float > VF;
typedef std::vector< VoidPointer > VVP;

int main(int argc, char** argv)
{
    VF vf;
    vf.push_back(13.0f);
    vf.push_back(14.0f);
    vf.push_back(15.0f);
    vf.push_back(16.0f);

    VVP vvp;
    vvp.push_back( (VoidPointer)const_cast<float *>( &(vf.front()) ) );

    VF data ( static_cast< float* >( vvp.at(0) ),
              static_cast< float* >( vvp.at(0) ) + vf.size() );

    std::cout << "data.size() is " << data.size() << std::endl;

    for(VF::const_iterator i = data.begin(); i != data.end(); ++i)
    {
        std::cout << "data contains " << *i << std::endl;
    }

    return 0;
}
但这会导致程序以std::bad_alloc终止,如果需要,我不介意复制。

这不是从
vvp.at(0)
到向量的转换,而是将浮点数组复制到新向量中。如果不知道长度,你就不能复制它。您只保存了指向第一个元素的指针,因此信息丢失

您可以制作
std::vector VVP
,并保存
&vf.front()
vf.size()
(或者开始和结束指针,如果您愿意的话)

您可以制作
std::vector
并存储指向向量的指针(即
vvp.push_back(&vf)
),现在根本不需要强制转换

编辑:如果您没有意识到:指针
&vf
&vf.front()
无关
vf
是一种包含指针
&vf.front()
(或获取指针的方法)的结构。只有地址
&vf.front()
中没有信息,您可以找到
&vf
这不是从
vvp.at(0)
到向量的转换,而是一个浮点数组到新向量的副本。如果不知道长度,你就不能复制它。您只保存了指向第一个元素的指针,因此信息丢失

#include <iostream>
#include <vector>

typedef void* VoidPointer;
typedef std::vector< float > VF;
typedef std::vector< VoidPointer > VVP;

int main(int argc, char** argv)
{
    VF vf;
    vf.push_back(13.0f);
    vf.push_back(14.0f);
    vf.push_back(15.0f);
    vf.push_back(16.0f);

    VVP vvp;
    vvp.push_back( (VoidPointer)const_cast<float *>( &(vf.front()) ) );

    VF data ( static_cast< float* >( vvp.at(0) ),
              static_cast< float* >( vvp.at(0) ) + vf.size() );

    std::cout << "data.size() is " << data.size() << std::endl;

    for(VF::const_iterator i = data.begin(); i != data.end(); ++i)
    {
        std::cout << "data contains " << *i << std::endl;
    }

    return 0;
}
您可以制作
std::vector VVP
,并保存
&vf.front()
vf.size()
(或者开始和结束指针,如果您愿意的话)

您可以制作
std::vector
并存储指向向量的指针(即
vvp.push_back(&vf)
),现在根本不需要强制转换


编辑:如果您没有意识到:指针
&vf
&vf.front()
无关
vf
是一种包含指针
&vf.front()
(或获取指针的方法)的结构。只有地址
&vf.front()
中没有信息让您找到
&vf
我能想到的唯一一件事是极其不可移植(而且同样疯狂)。每个向量分配一个连续的内存数组。任何分配函数都必须跟踪已分配的字节数,以便仅在分配地址的开头就可以取消分配字节

#include <iostream>
#include <vector>

typedef void* VoidPointer;
typedef std::vector< float > VF;
typedef std::vector< VoidPointer > VVP;

int main(int argc, char** argv)
{
    VF vf;
    vf.push_back(13.0f);
    vf.push_back(14.0f);
    vf.push_back(15.0f);
    vf.push_back(16.0f);

    VVP vvp;
    vvp.push_back( (VoidPointer)const_cast<float *>( &(vf.front()) ) );

    VF data ( static_cast< float* >( vvp.at(0) ),
              static_cast< float* >( vvp.at(0) ) + vf.size() );

    std::cout << "data.size() is " << data.size() << std::endl;

    for(VF::const_iterator i = data.begin(); i != data.end(); ++i)
    {
        std::cout << "data contains " << *i << std::endl;
    }

    return 0;
}

AFAIK,C++标准没有指定如何保存这本书,因此,这是每个编译器。一种方法是在实际分配地址之前写一个计数,我相信这是VisualC++编译器所做的。(例如,如果在0x104分配,则32位计数可存储在0x100)。同样,您必须知道您的特定编译器是如何进行此簿记的

无论如何,关键是,一旦你这样做了,一个小小的指针算法和反引用理论上可以查找分配的大小(我当然假设你仍然在使用一个带有默认分配器的向量),并计算出仅仅使用一个空指针实际分配了多少个浮点数

下面是一个在Visual Studio中以32位调试模式工作的示例:

#include <iostream>
#include <vector>

size_t bytes_allocated( void* p )
{
#ifndef _DEBUG
#error Doesn't work
#endif // _DEBUG
    size_t const offset = 12;
    size_t const counter_size = 4;
    size_t const total_offset = offset + counter_size;
    void* counter_address = ((char*)p)-total_offset;
    size_t* count = reinterpret_cast<size_t*>(counter_address);
    return *count;
}

int main(int argc, char* argv[])
{
    typedef float test_type;
    std::vector<test_type> v;
    v.push_back(23);
    v.push_back(23);
    v.push_back(23);
    size_t count = bytes_allocated(&v[0]);
    std::cout<<count<<" bytes allocated\n";
    std::cout<<count/sizeof(test_type)<<" items allocated\n";
    return 0;
}

我能想到的唯一一件事就是极其不可移植(而且同样疯狂)。每个向量分配一个连续的内存数组。任何分配函数都必须跟踪已分配的字节数,以便仅在分配地址的开头就可以取消分配字节

AFAIK,C++标准没有指定如何保存这本书,因此,这是每个编译器。一种方法是在实际分配地址之前写一个计数,我相信这是VisualC++编译器所做的。(例如,如果在0x104分配,则32位计数可存储在0x100)。同样,您必须知道您的特定编译器是如何进行此簿记的

无论如何,关键是,一旦你这样做了,一个小小的指针算法和反引用理论上可以查找分配的大小(我当然假设你仍然在使用一个带有默认分配器的向量),并计算出仅仅使用一个空指针实际分配了多少个浮点数

下面是一个在Visual Studio中以32位调试模式工作的示例:

#include <iostream>
#include <vector>

size_t bytes_allocated( void* p )
{
#ifndef _DEBUG
#error Doesn't work
#endif // _DEBUG
    size_t const offset = 12;
    size_t const counter_size = 4;
    size_t const total_offset = offset + counter_size;
    void* counter_address = ((char*)p)-total_offset;
    size_t* count = reinterpret_cast<size_t*>(counter_address);
    return *count;
}

int main(int argc, char* argv[])
{
    typedef float test_type;
    std::vector<test_type> v;
    v.push_back(23);
    v.push_back(23);
    v.push_back(23);
    size_t count = bytes_allocated(&v[0]);
    std::cout<<count<<" bytes allocated\n";
    std::cout<<count/sizeof(test_type)<<" items allocated\n";
    return 0;
}

在你的最后一行中将
vvp.at(0)
更改为
&vvp.at(0)
会起作用吗?我不明白
vvp.push_是什么意思((VoidPointer)/*…*/)调用旨在执行的操作。看起来您试图将
vf
的第一个元素强制转换为
void*
并将其附加到
vvp
。为什么要进行常量转换?为什么下面这行假设在
vvp
中有
vf.size()
元素,而只添加了一个元素?@Matt Phillips:不幸的是,我得到的静态数据无效_cast@jogojapan:其中一些代码与不在我控制下的外部库api的编组有关,这一行获取了对vf第一个元素的常量引用的地址,删除常量并强制转换为void*,在你的最后一行中将
vvp.at(0)
更改为
&vvp.at(0)
,我不明白
vvp.push_是什么意思((VoidPointer)/*/)调用旨在执行的操作。看起来您试图将
vf
的第一个元素强制转换为
void*
并将其附加到
vvp
。为什么要进行常量转换?为什么下面这行假设在
vvp
中有
vf.size()
元素,而只添加了一个元素?@Matt Phillips:不幸的是,我得到的静态数据无效_cast@jogojapan:其中一些代码与不在我控制下的外部库api的编组有关,该行获取对vf的第一个元素的常量引用的地址,删除常量并强制转换为void*您还可以使用boost::any的向量,并在其中添加各种类型,如果这是您想要的。@Ben Jackson-感谢您的回复“这不是从vvp.at(0)转换为向量”,是的,这就是为什么我用构造器这个词来表示线条