sizeof()可能会被优化掉吗?

时间:2015-10-11 21:20:22

标签: c++

我有这个结构:

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的流程,但这是我第三次重建这个软件,它是我的宝贝,我不在乎它是否永远不会看到光只要它完美。

4 个答案:

答案 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