1

使用 memmove/memcpy 使用构造函数参数初始化对象是否安全?
似乎没有人使用这种方法,但是当我尝试它时效果很好。
在堆栈中传递的参数会导致问题吗?

假设我有一堂课foo如下,

class foo
{
  int x,y;
  float z;
  foo();
  foo(int,int,float); 
};

我可以按如下方式使用 memmove 初始化变量吗?

foo::foo(int x,int y,float z)
{
  memmove(this,&x, sizeof(foo));
}
4

4 回答 4

3

这是未定义的行为。

所示代码不会尝试初始化类变量。它尝试memmove() 到类指针上,并假定类的大小为2*sizeof(int)+sizeof(float). C++ 标准不保证这一点。

此外,显示的代码还假定传递给构造函数的参数的布局将与 this 的成员的布局相同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));
}

当然,这没有任何用处,但这会是安全的。

于 2016-09-24T14:37:28.613 回答
1

我们应该忘记小的效率,比如大约 97% 的时间:过早优化是万恶之源。然而,我们不应该放弃那关键的 3% 的机会。——唐纳德·克努斯

您不应该尝试优化您不确定是否需要的代码。我建议您在能够执行这种优化之前分析您的代码。这样,您就不会浪费时间改进不会影响应用程序整体性能的某些代码的性能。

通常,编译器足够聪明,可以猜出你想用你的代码做什么,并生成保持相同功能的高效代码。为此,您应该确保启用编译器优化(-Olevel通过编译器命令参数标记或切换单个优化)。

例如,std::copy当编译器确定这样做很简单(例如数据是连续的)时,我已经看到一些编译器转换为 memcpy。

于 2016-09-24T16:36:02.730 回答
1

不,这不安全,因为根据标准,由于对齐/填充,不能保证成员立即彼此紧随其后。更新后,情况更糟,因为传递参数的位置及其顺序使用起来不安全。

于 2016-09-24T14:40:30.233 回答
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)
{ }
于 2016-09-24T17:44:32.993 回答