gpt4 book ai didi

c++ - 检查 POD 变量的变化

转载 作者:太空宇宙 更新时间:2023-11-04 11:25:05 25 4
gpt4 key购买 nike

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

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 和 free 逻辑。有什么建议么?我特别不喜欢 oldshool malloc、memcpy 和 memcmp 东西,但我不知道如何做。

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

最佳答案

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

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;
}

这样您就可以为每种类型获得一个映射,并且您不必担心无意中弄乱了别名。您确实需要定义 operator != 并为您的类型创建一个有效的复制构造函数,但这比盲目使用 memcmpmemcpy 要好得多.

如果需要比较数组,您还可以对数组进行进一步的模板特化(代码会多一些,但不会很复杂)

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

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

或者您可以使用 char* 为所有值设置别名。这将允许您对所有内容使用单个映射(就像您之前所做的那样,但它没有 memcpy/memcmp)。它只适用于 POD。我们可以在覆盖缓冲区时手动调用析构函数,但由于在类的析构函数中没有很好的方法来执行此操作,因此最好完全忽略堆分配的数据。

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;
}
};

关于c++ - 检查 POD 变量的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26944061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com