我有这个结构:
struct KVP {
uint32_t KeyLenB;
uint32_t ValLenB;
void Set (char* pKey, uint32_t KeyLenB, char* pVal, uint32_t ValLenB) {
this->KeyLenB = KeyLenB;
this->ValLenB = ValLenB;
memcpy(this + sizeof(KVP), pKey, KeyLenB);
memcpy(this + sizeof(KVP) + KeyLenB, pVal, ValLenB);
}
snip
};
那些进入预先分配的内存块。另一种方法是在长度字段之后添加另一个成员并仅引用它,但sizeof(KVP)只返回长度字段的大小,在其余代码中更合适。
所以无论如何,因为这个函数会被调用很多,我想知道“this + sizeof(this)”是否会比指向潜在的第3个成员更慢?
是的,我知道这种不必要的优化和yadayada的流程,但这是我第三次重建这个软件,它是我的宝贝,我不在乎它是否永远不会看到光只要它完美。
答案 0 :(得分:11)
sizeof
不是函数,它是一个运算符,它在编译时在任何代码运行之前进行求值。因此,使用sizeof
会在运行时产生零成本。
答案 1 :(得分:0)
{{1}}。它的成本与任何其他常量一样多,包括另一个成员的偏移量。
所以是的,它肯定会被优化掉。
答案 2 :(得分:0)
在C中,这是常见的/可行的。在C ++中,KVP永远不会被继承。但是,Set不能是成员函数,尽管它可能是构造函数和/或类特定的新运算符,因为构造函数/ new必须分配额外的空间:在调用Set之前KeyLenB + 1 + ValLenB + 1。
所以,如果你真的想按照书面形式这样做,可以考虑把它放在一个.c文件中[带有适当的“extern C”东西],这样你就可以使用malloc并且不会与构造函数碰撞等等。这可能是比将它放在.cpp中更容易,并禁用所有标准构造函数/析构函数等。
但是,你可能不得不采取另一种方式来改变你的可变长度疼痛。考虑将KVP拆分为KVP和“字符串”结构。你有两个选择:
struct mystring {
uint32_t str_len;
char str_data[0];
};
struct KVP {
mystring *kvp_key;
mystring *kvp_val;
};
mystring *
newstring(char *val)
{
struct mystring *str;
uint32_t len;
len = strlen(val);
str->str_len = len;
str = malloc(sizeof(struct mystring) + len + 1);
memcpy(str->str_data,val,len + 1);
return str;
}
上述新闻字符串与您的Set尝试执行的操作类似。但请考虑替代方案:
struct mystring {
uint32_t str_len;
char *str_data;
};
struct KVP {
mystring kvp_key;
mystring kvp_val;
};
mystring *
newstring(char *val)
{
struct mystring *str;
uint32_t len;
len = strlen(val);
str->str_len = len;
str->_str_data = malloc(sizeof(struct mystring) + len + 1);
memcpy(str->str_data,val,len + 1);
return str;
}
答案 3 :(得分:0)
关闭袖口代码,未编译:
class Key_and_value
{
private:
int32_t key_length_;
int32_t value_length_;
char data_[1];
public:
Key_and_value(
char const* const key,
int32_t const key_length,
char const* const value,
int32_t value_length
)
: key_length_( key_length )
, value_length( value_length )
{
memcpy( data, key, key_length );
memcpy( data + key_length, value, value_length );
}
};
这里的关键概念是使用构造函数。使用setter函数,您可以更改对象的内存占用空间大小,可能是在其后放置了一些其他此类可变长度对象之后。
要在预先存在的存储空间中构建对象,您可以添加<new>
标头并使用新的展示位置,例如::new( my_storage ) Key_and_value( blah... )
。但请确保存储从适当对齐的地址开始。如有必要,请阅读对齐。
此代码中没有sizeof
所以关于这个的问题没有实际意义。但无论如何,在C ++中,这是一个编译时表达式。它几乎没有运行时成本。
正如其他人已经说过的那样,创建正确的代码比创建快速代码要重要得多。如果代码非常快,如果代码也非常不正确(事实上,如果代码可以任意不正确,那么它也可以任意快速,什么都不做)并不重要。所以一般的建议是:不要这样做,至少不要一开始,如果你觉得某些优化可能正是需要的话,那么首先 MEASURE 。