我的课程看起来大致如下:
template<std::size_t dim>
class Foo {
public:
Foo(void const * const data);
private:
double vals[dim];
}
对于构造函数,我知道void* data
指向一个float
值数组(维度为dim)。现在我想在该构造函数的初始化列表中初始化vals
- 数组(最好)。
更糟糕的是,指向的浮点数不一定必须与内存对齐。
我怎么能有效地做到这一点?
关于下面的讨论,请允许我先说明我的设计优先事项。这可能有助于您专注于对我来说最重要的问题。
老实说,如果我们需要构造函数体来获得快速算法,这对我来说也没问题。重点是原始力量。
答案 0 :(得分:1)
如果您担心传递的指针未与float
边界对齐(例如,文件映射等),那么您可以编写类似
template<std::size_t dim>
class Foo {
public:
Foo(void const * const data)
{
float temp[dim];
memcpy( &temp, data, dim * sizeof( float ) );
std::copy( temp, temp + dim, vals );
}
private:
double vals[dim];
}
可能是一个过于热心且不那么便携的解决方案:
template<std::size_t dim>
class Foo {
public:
Foo(void const * const data)
{
if( static_cast<long>( data ) % sizeof( float ) == 0 ) {
const float *temp = data;
std::copy( temp, temp + dim, vals );
} else {
float temp[dim];
memcpy( &temp, data, dim * sizeof( float ) );
std::copy( temp, temp + dim, vals );
}
}
private:
double vals[dim];
}
在初始化列表中初始化不会使您的代码更快,只有在可能的情况下才是方便。
如果您非常关注性能,我会将此if
包装在一个宏中,并且仅在架构上使用if
,这需要正确对齐访问(x86不是一个,它只是慢一点在x86)。
评论中提出的另一个解决方案,谢谢 Steve Jessop。它侧重于减少临时变量大小。
double *dest = vals;
float tmp;
void const *first = data;
void const *last = data + dim * sizeof(float);
while( first != last ) {
memcpy( &tmp, first, sizeof(float) );
first += sizeof(float);
*dest++ = tmp;
}
可能需要进行一些微观基准/分解。
答案 1 :(得分:0)
由于float
的大小与double
不同,我认为唯一的方法是从一个数组手动分配到另一个数组。
是否可以将vals
更改为float
的数组?这样您就可以使用data
将memcpy
数组复制到其中。因为在float
数组中存储double
时没有精确度,除非您稍后更改vals
以使用double
的高精度,否则不会从使用double
s获得任何东西。
答案 2 :(得分:0)
你为什么要隐藏这个类型?
这有什么问题:
template<std::size_t dim>
class Foo {
public:
Foo(float const * const data);
private:
double vals[dim]
}
template<std::size_t dim>
Foo< dim >::Foo(float const * const data) : vals()
{
std::copy( data, data+dim, &vals[0] );
}
修改强>
如果您切换到std::vector
,则可以像这样初始化:
class Foo {
public:
Foo(float const * const dataBegin,float const * const dataEnd);
private:
std::vector< double > vals;
}
Foo::Foo(float const * const dataBegin,float const * const dataEnd) : vals( dataBegin, dataEnd )
{
}
答案 3 :(得分:0)
您无法在当前C ++标准的初始化列表中初始化数组。您可以利用事先知道尺寸的事实来使用std::vector
;
template<std::size_t dim>
class Foo {
public:
Foo(float const * const data) : vals(dim) // fix the vector size
{
for(std::size_t i=0; i<dim; i++)
vals[i] = data[i]; // assignment
}
private:
std::vector<double> vals;
};
我不能说vector<>
和原始数据一样有效;但它们经过了很好的优化和异常安全。