我经常使用memcpy来复制C / C ++中的结构。 我看到有人使用等号在C / C ++中直接复制struct。 例如:
struct A { char* name; int value; };
struct B { struct A happy[10]; };
struct A a1, a2;
struct B b1, b2;
memcpy(&a1, &a2, sizeof(struct A));
b1 = b2;
memcpy和等号之间的效率差异是什么?
答案 0 :(得分:5)
现在已经删除了c ++标记,我们正在谈论C而不是C ++。
假设a1
和a2
是同一struct
类型的变量
memcpy(&a1, &a2, sizeof(struct A));
和
a1 = a2;
做同样的事情。
但如果分配运算符实际使用memcpy
,则完全取决于编译器。
答案 1 :(得分:3)
在C ++中,结构可以是普通的旧数据(C类型)或复杂的 - 需要调用构造和复制构造函数。
memcpy和=之间的区别是=工作。
当=应用于复杂结构时,它会按照规则复制每个成员。 当=应用于一个简单的结构(普通旧数据或POD)时,它会执行" memcpy"。
在C复合体中,最初不允许复制,因此一些旧代码会使用=来记忆。在C中,它们等同于相同的操作。
答案 2 :(得分:2)
C!= C ++ ...让我们假设C情况,你不能重载赋值运算符。
值得查看测试用例的clang输出:
struct A { char* name; int value; };
struct B { struct A happy[10]; };
void foo() {
struct A a1, a2;
struct B b1, b2;
memcpy(&a1, &a2, sizeof(struct A));
b1 = b2;
}
运行以下命令使clang输出LLVM字节码:
clang -S -emit-llvm foo.c -o -
哪个输出
; Function Attrs: nounwind uwtable
define void @foo() #0 {
%a1 = alloca %struct.A, align 8
%a2 = alloca %struct.A, align 8
%b1 = alloca %struct.B, align 8
%b2 = alloca %struct.B, align 8
%1 = bitcast %struct.A* %a1 to i8*
%2 = bitcast %struct.A* %a2 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %2, i64 16, i32 8, i1 false)
%3 = bitcast %struct.B* %b1 to i8*
%4 = bitcast %struct.B* %b2 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %4, i64 160, i32 8, i1 false)
ret void
}
有趣的是,在两种情况下(呼叫memcpy
或分配运营商)都会生成对@llvm.memcpy.p0i8.p0i8.i64
的调用!