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)转换为向量”,是的,这就是为什么我用构造器这个词来表示线条