C++ 直接访问唯一类数据成员
我有一个具有唯一公共数据成员的类,该成员是内置类型:C++ 直接访问唯一类数据成员,c++,c++11,templates,memory-address,C++,C++11,Templates,Memory Address,我有一个具有唯一公共数据成员的类,该成员是内置类型: class foo { public: int data; foo(int dataIn) : data(dataIn) {} virtual ~foo() {} // Some other class methods protected: // Some internal helper class methods }; 在另一个类中,我想使用memcpy方法: template<typen
class foo {
public:
int data;
foo(int dataIn) : data(dataIn) {}
virtual ~foo() {}
// Some other class methods
protected:
// Some internal helper class methods
};
在另一个类中,我想使用memcpy
方法:
template<typename T>class bar {
protected:
T data;
public:
bar() {}
virtual ~bar() {}
void read(unsigned char* readBuff, const std::size_t &readSize) {
// Some stuff
std::memcpy(readBuff, &(this->data), readSize);
// Some stuff
}
};
我得到了4
,所以foo似乎正好是int的大小,所以我自然会认为直接读/写x
,即使不指定x.data
也会写数据。这是真的吗
我需要与C++11兼容。否
对于具有虚函数的类,编译器通常会在类的开头插入一些元数据。不能假定实例的地址也是其第一个成员的地址
您可以使用if constexpr
来区分这两种情况:
if constexpr ( std::is_same_v<std::decay_t<T>, foo> ) {
std::memcpy(readBuff, &(this->data.data), readSize);
} else {
std::memcpy(readBuff, &(this->data), readSize);
}
如果constexpr(std::is_same_v){
std::memcpy(readBuff,&(this->data.data),readSize);
}否则{
std::memcpy(readBuff,&(this->data),readSize;
}
否
对于具有虚函数的类,编译器通常会在类的开头插入一些元数据。不能假定实例的地址也是其第一个成员的地址
您可以使用if constexpr
来区分这两种情况:
if constexpr ( std::is_same_v<std::decay_t<T>, foo> ) {
std::memcpy(readBuff, &(this->data.data), readSize);
} else {
std::memcpy(readBuff, &(this->data), readSize);
}
如果constexpr(std::is_same_v){
std::memcpy(readBuff,&(this->data.data),readSize);
}否则{
std::memcpy(readBuff,&(this->data),readSize;
}
否
具有虚拟成员的任意类型的布局由实现定义。不能保证在foo中偏移量为0的位置有数据
您可以将bar
完全专用于foo
template<>class bar<foo> {
protected:
foo data;
public:
bar() {}
virtual ~bar() {}
void write(unsigned char* readBuff, const std::size_t &readSize) {
// Some stuff
std::memcpy(readBuff, &(this->data.data), readSize);
// Some stuff
}
};
没有
具有虚拟成员的任意类型的布局由实现定义。不能保证在foo中偏移量为0的位置有数据
您可以将bar
完全专用于foo
template<>class bar<foo> {
protected:
foo data;
public:
bar() {}
virtual ~bar() {}
void write(unsigned char* readBuff, const std::size_t &readSize) {
// Some stuff
std::memcpy(readBuff, &(this->data.data), readSize);
// Some stuff
}
};
经过几次尝试,我找到了另一种实现它的方法,而不必像@Caleth的解决方案那样在read()中实例化一个新的helper
对象(虽然这很好),因此哪个应该具有更好的性能:
class foo {
public:
int data;
foo(int dataIn) : data(dataIn) {}
virtual ~foo() {}
// Some other class methods
protected:
// Some internal helper class methods
};
template<bool ISFOO> struct IsFoo_ {
enum {
IS_FOO_ = ISFOO
};
};
template<typename T>class bar {
protected:
T data;
public:
bar() {}
virtual ~bar() {}
struct CRV {
enum {
USES_FOO = std::is_same<T, foo>::value
};
};
void* getCopyable() {
return getCopyable_<CRV::USES_FOO>();
}
void read(unsigned char* readBuff, const std::size_t &readSize) {
// Some stuff
std::memcpy(readBuff, this->getCopyable(), readSize);
// Some stuff
}
private:
// Caller method
template<bool ISFOO> inline void* getCopyable_() {
return getCopyable_(IsBitVector_<ISFOO>());
}
// Generic method
template<bool ISFOO> inline void* getCopyable_(IsFoo_<ISFOO>) {
return nullptr;
}
// Specializations
inline void* getCopyable_(IsFoo_<true>) {
return reinterpret_cast<void*>(&(this->data.data));
}
inline void* getCopyable_(IsFoo_<false>) {
return reinterpret_cast<void*>(&(this->data));
}
};
class-foo{
公众:
int数据;
foo(int-dataIn):数据(dataIn){}
虚拟~foo(){}
//其他一些类方法
受保护的:
//一些内部助手类方法
};
模板结构IsFoo\u{
枚举{
IS_FOO=ISFOO
};
};
模板类栏{
受保护的:
T数据;
公众:
bar(){}
虚拟~bar(){}
结构CRV{
枚举{
USES\u FOO=std::is\u same::value
};
};
void*getCopyable(){
返回getCopyable_u2;();
}
无效读取(无符号字符*readBuff,常量std::size\u t和readSize){
//一些东西
std::memcpy(readBuff,this->getCopyable(),readSize);
//一些东西
}
私人:
//调用方方法
模板内联void*GetCopyTable{
返回getCopyable_u3;(IsBitVector_3;());
}
//通用方法
模板内联void*GetCopyTable(IsFoo){
返回空ptr;
}
//专业
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(this->data.data));
}
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(此->数据));
}
};
经过几次尝试,我找到了另一种实现它的方法,而不必像@Caleth的解决方案那样在read()中实例化一个新的助手
对象(虽然这很好),因此哪个应该有更好的性能:
class foo {
public:
int data;
foo(int dataIn) : data(dataIn) {}
virtual ~foo() {}
// Some other class methods
protected:
// Some internal helper class methods
};
template<bool ISFOO> struct IsFoo_ {
enum {
IS_FOO_ = ISFOO
};
};
template<typename T>class bar {
protected:
T data;
public:
bar() {}
virtual ~bar() {}
struct CRV {
enum {
USES_FOO = std::is_same<T, foo>::value
};
};
void* getCopyable() {
return getCopyable_<CRV::USES_FOO>();
}
void read(unsigned char* readBuff, const std::size_t &readSize) {
// Some stuff
std::memcpy(readBuff, this->getCopyable(), readSize);
// Some stuff
}
private:
// Caller method
template<bool ISFOO> inline void* getCopyable_() {
return getCopyable_(IsBitVector_<ISFOO>());
}
// Generic method
template<bool ISFOO> inline void* getCopyable_(IsFoo_<ISFOO>) {
return nullptr;
}
// Specializations
inline void* getCopyable_(IsFoo_<true>) {
return reinterpret_cast<void*>(&(this->data.data));
}
inline void* getCopyable_(IsFoo_<false>) {
return reinterpret_cast<void*>(&(this->data));
}
};
class-foo{
公众:
int数据;
foo(int-dataIn):数据(dataIn){}
虚拟~foo(){}
//其他一些类方法
受保护的:
//一些内部助手类方法
};
模板结构IsFoo\u{
枚举{
IS_FOO=ISFOO
};
};
模板类栏{
受保护的:
T数据;
公众:
bar(){}
虚拟~bar(){}
结构CRV{
枚举{
USES\u FOO=std::is\u same::value
};
};
void*getCopyable(){
返回getCopyable_u2;();
}
无效读取(无符号字符*readBuff,常量std::size\u t和readSize){
//一些东西
std::memcpy(readBuff,this->getCopyable(),readSize);
//一些东西
}
私人:
//调用方方法
模板内联void*GetCopyTable{
返回getCopyable_u3;(IsBitVector_3;());
}
//通用方法
模板内联void*GetCopyTable(IsFoo){
返回空ptr;
}
//专业
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(this->data.data));
}
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(此->数据));
}
};
您可以使用offsetof
“如果您分配该类型的对象,并在结构的开头获得一个字节*
,您可以使用offsetof
找出每个成员的位置。如果您使用该指针偏移量,并将其转换回正确的类型,它将为您提供一个指向该成员的指针。”-.@user202729offsetof
声明:“类型应该是一个标准布局类(包括联合)。”和“标准布局类是一个类[…]:(1)没有虚拟函数和虚拟基类。”@user202729正如WorldSEnder所说,文档说明在我的情况下这是未定义的行为。您可以使用offsetof
。“如果分配该类型的对象,并在结构的开头获得一个字节*
,则可以使用offsetof
查找每个成员的位置。如果您使用该指针偏移量,并将其转换回正确的类型,它将为您提供一个指向成员的指针。“-@user202729offsetof
声明:“类型应为标准布局类(包括联合)。”和“标准布局类为[…]类:(1)没有虚拟函数和虚拟基类。“@user202729正如WorldSEnder所说,文档中说在我的情况下这是未定义的行为。我忘了告诉我需要符合c++11。如果constexpr不工作!我忘了告诉你我需要什么