检查POD变量的变化 [英] Check for changes in POD variables

查看:227
本文介绍了检查POD变量的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种有效的方法来检查POD变量是否在两个周期之间改变。我想出了这个解决方案:

I'm looking for an efficient way to check if a POD variable is altered between two cycles. I've come up with this solution:

class Foo {
public:
    template<typename T>
    bool isChanged(T& entry);
    void endCycle();
private:
     std::map<void*,size_t> entryMap;  // <Address orig.,Size>
     std::map<void*,void*>oldVals;     // <Address orig., Address cpy.> 
};

template<typename T> bool Foo::isChanged(T& entry)
{
    entryMap[&entry] = sizeof(T);
    if(oldVals[&entry] == NULL)
        return false;
    if(memcmp(&entry, oldVals[&entry], entryMap[&entry]))
        return true;
    else
        return false;
}

void Foo::endCycle()
{   
    // Copy all the bytes to save them for the next cycle
    for(  std::map<void*,size_t>::iterator entryIt = entryMap.begin();
          entryIt != entryMap.end();
          ++entryIt)
    {
        if(oldVals[entryIt->first] == NULL)
            oldVals[entryIt->first] = malloc(entryIt->second);
        memcpy(oldVals[entryIt->first], entryIt->first, entryIt->second);
    }
}

现在我可以这样使用:

Foo gBar;
void aFunction()
{
int ar;
char ba[3][3];
// Some code where ar and ba are filled
if(gBar.isChanged(ar))
    // Do Something
if(gBar.isChanged(ba))
    // Do Something
gBar.endCycle();
}

这是一种高效的方法吗?我的目标是一个很容易在各种循环调用函数中使用的方法。我清除了所有的init和自由逻辑从代码。有什么建议么?我特别不喜欢oldshool malloc,memcpy和memcmp的东西,但我不知道任何其他方式如何做。

Is this an efficient way? My goal was a method which is very easy to use inside various cyclically called functions. I cleaned all the init and free logic from the code. Any suggestions? I especially don't like the oldshool malloc, memcpy and memcmp stuff but i don't know any other way how to do it.

编辑:找到了一个很好的解决方案红色警报建议。

Found a good solution based on Red Alerts suggestions.

推荐答案

我认为你可以在这里更有效地使用模板。

I think you can use templates a little more effectively here.

template <typename T>
class Foo
{
public:
    static std::map<T*, T> values;

    static bool isChanged(T& entry)
    {    
        auto it = values.find(&entry);

        if(it == values.end())
        {
            values[&entry] = entry;
        }
        else if(entry != it->second)
        {    
            it->second = entry;
            return true;
        }

        return false;
    }
};


template <typename T>
std::map<T*, T> Foo<T>::values;

int main() {

    int ar = 3;
    cout << Foo<int>::isChanged(ar) << endl; // 0

    ar = 4;

    cout << Foo<int>::isChanged(ar) << endl; // 1

    for(auto& value : Foo<int>::values)
        cout << value.second << endl; // 4

    return 0;
}

这样你就可以得到一个 map 每种类型,你不必担心无意中混淆别名。你需要定义 operator!= 并且有一个工作副本构造函数为你的类型,但是这比盲目使用 memcmp memcpy

This way you get one map per type, and you don't have to worry about inadvertently messing up an alias. You do need to define operator != and have a working copy constructor for your types, but that is much better than blindly using memcmp and memcpy.

如果需要比较数组,将更多的代码,但没有什么很复杂)

You can also make further template specializations for arrays if you need to compare those (will be a bit more code, but nothing very complicated)

编辑:为了让你开始,这是你的模板签名应该是:

To get you started, this is what your template signature should look like:

template<class T, size_t N> bool isChanged(T(&entry)[N]); //will be called for stack allocated arrays

或者可以使用char * 。这将让你使用单个地图的一切(像你以前做的,但这没有 memcpy / memcmp )。它只适用于POD。我们可以在覆盖缓冲区时手动调用析构函数,但是由于在类的析构函数中没有很好的方法来做到这一点,所以最好不要使用堆分配的数据。

Or you can use char* to alias all of your values. This will let you use a single map for everything (like you were doing before, but this has no memcpy/memcmp). It will only work for POD. We could manually call the destructor when overwriting the buffer, but since there is no good way to do this in the class's destructor, it's probably best to leave out heap allocated data altogether.

class Foo
{
    std::map<char**, char*> values;

public:
    ~Foo()
    {
        for(auto& value : values)
        {
            delete[] value.second;
        }
    }

    template<typename T> bool isChanged(T& entry)
    {
        char** addr = reinterpret_cast<char**>(&entry);
        auto it = values.find(addr);

        if(it == values.end())
        {
            alignas(T) char* oldBuf = new char[sizeof(T)];
            T* oldEntry = new(oldBuf) T;
            *oldEntry = entry;
            values[addr] = oldBuf;
        }
        else if(entry != *(reinterpret_cast<T*>(it->second)))
        {
            T* oldEntry = new(it->second) T;
            *oldEntry = entry;
            return true;
        }

        return false;
    }
};

这篇关于检查POD变量的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆