我们来看一个简单的例子:
struct some_struct {
std::string str;
int a, b, c;
}
some_struct abc, abc_copy;
abc.str = "some text";
abc.a = 1;
abc.b = 2;
abc.c = 3;
abc_copy = abc;
Run Code Online (Sandbox Code Playgroud)
然后abc_copy是一个精确复制的abc..怎么可能没有定义=操作符?
(在处理一些代码时,这让我感到意外..)
我想以通用的方式比较结构,我已经做了这样的事情(我不能分享实际的来源,所以如果有必要,请询问更多细节):
template<typename Data>
bool structCmp(Data data1, Data data2)
{
void* dataStart1 = (std::uint8_t*)&data1;
void* dataStart2 = (std::uint8_t*)&data2;
return memcmp(dataStart1, dataStart2, sizeof(Data)) == 0;
}
Run Code Online (Sandbox Code Playgroud)
这主要按预期工作,但有时即使两个 struct 实例具有相同的成员(我已经使用 eclipse 调试器进行了检查),它也会返回 false。经过一番搜索,我发现memcmp由于使用的结构被填充,这可能会失败。
有没有更合适的方法来比较对填充无动于衷的内存?我无法修改使用的结构(它们是我正在使用的 API 的一部分),并且使用的许多不同结构具有一些不同的成员,因此无法以通用方式单独比较(据我所知)。
编辑:不幸的是,我被 C++11 困住了。应该早点提到这个...
我正在研究一些具有高级接口的低级代码,并且需要比较运算符来进行普通旧数据类型(如FILETIME struct)的单元测试,但由于C++甚至不提供成员比较,所以我写了这样的:
template <typename Type>
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b) {
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,这是一个好方法还是有一些隐藏的恶魔会让我在开发周期后期遇到麻烦,但它现在有点工作.
N3797::3.9/4 [basic.types] :
类型T的对象的对象表示是由类型T的对象占据的N个无符号字符对象的序列,其中N等于sizeof(T).对象的值表示是保存类型T的值的位集.对于简单的可复制类型,值表示是对象表示中的一组位,用于确定值,该值是实现的一个离散元素 -定义的值集
N3797::3.9.1 [basic.fundamental] 说:
对于窄字符类型,对象表示的所有位都参与值表示.
考虑以下结构:
struct A
{
char a;
int b;
}
Run Code Online (Sandbox Code Playgroud)
我认为,A由于实现添加了填充,因此对象表示的所有位都不参与值表示.但其他基本类型呢?标准说:
N3797::3.9.1 [basic.fundamental]
对于窄字符类型,对象表示的所有位都参与值表示.这些要求不适用于其他类型.
我无法想象为什么它不适合说int或long.什么原因?你能澄清一下吗?
我对当前的 C++ 标准感兴趣,并且对http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/上的链接有点困惑。新版本应该是什么?我应该寻找什么标题?是“工作草案,编程语言 C++ 标准”还是“编程语言 \xe2\x80\x94 C++ ”?这些论文有什么区别?为什么N4141纸张有密码保护,而较新的N4296则没有?
\n\n问题在哪里可以找到当前的 C 或 C++ 标准文档?有一个很好的草稿列表,但我仍然无法分辨草稿的“稳定”版本是什么,即我可以使用什么作为 C++11 的参考?
\n考虑复制一个不需要特殊复制语义的简单结构.
struct A
{
char i
int i;
long l;
double b;
//...maybe more member
}
struct A a;
a.c = 'a'; //skip other member just for illustrate
struct A b;
memset(&a, 0, sizeof(a));
b.c = a.c;
//...for other members, the first way to assign
memcpy(&b, &a, sizeof(b)); //the second way
b = a; //the third way
Run Code Online (Sandbox Code Playgroud)
3种方法做同样的事情,似乎所有这些方法都是正确的.我曾经使用'memcpy'来复制简单的结构,但现在似乎'='可以做同样的事情.那么使用memcpy和'=' 之间有什么区别吗?