使用memmove / memcpy用构造函数参数初始化对象是否安全? 似乎没有人使用这种方法但是当我尝试它时它工作正常 参数在堆栈中传递会导致问题吗?
说我有一个课程class foo
{
int x,y;
float z;
foo();
foo(int,int,float);
};
如下,
foo::foo(int x,int y,float z)
{
memmove(this,&x, sizeof(foo));
}
我可以使用memmove初始化变量,如下所示吗?
{{1}}
答案 0 :(得分:2)
这是未定义的行为。
显示的代码不会尝试初始化类变量。它尝试memmove
()到类指针上,并假设类的大小为2*sizeof(int)+sizeof(float)
。 C ++标准不保证。
此外,显示的代码还假设传递给构造函数的参数布局与此POD
成员的布局布局相同。这也是C ++标准没有规定的。
使用memmove
初始化单个类成员是安全的。例如,以下是安全的:
foo::foo(int x_,int y_,float z_)
{
memmove(&x, &x_, sizeof(x));
memmove(&y, &y_, sizeof(y));
memmove(&z, &z_, sizeof(z));
}
当然,这没什么用处,但这是安全的。
答案 1 :(得分:1)
不,这不安全,因为基于标准,由于对齐/填充,成员不能保证立即紧接着。 更新后,这更糟糕,因为传递的参数及其顺序的位置不安全。
答案 2 :(得分:1)
我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源。然而,我们不应该放弃那个关键的3%的机会。 - 唐纳德克努特
您不应该尝试优化您不确定需要的代码。在您能够执行此类优化之前,我建议您配置代码。通过这种方式,不会浪费时间提高某些代码的性能,这些代码不会影响应用程序的整体性能。
通常,编译器足够智能,可以猜测您要对代码执行什么操作,并生成保持相同功能的高效代码。为此,您应该确保启用编译器优化(-Olevel
标志或通过编译器命令参数切换单个标记)。
例如,我发现当编译器确定这样做很简单时(例如数据是连续的),有些编译器会将std::copy
转换为memcpy。
答案 3 :(得分:0)
不,这不安全。这是未定义的行为。
代码
foo::foo(int x,int y,float z)
{
memmove(this,&x, sizeof(foo));
}
与使用初始化列表相比,甚至不会保存任何输入
foo::foo(int x,int y,float z) : x(x), y(y), z(z)
{ }