在 C++ 的构造函数中使用 memmove 初始化整个对象
Using memmove to initialize entire object in constructor in C++
使用 memmove/memcpy 初始化带有构造函数参数的对象是否安全?
好像没有人用过这个方法,但是我试了一下效果很好。
在堆栈中传递的参数会导致问题吗?
假设我有一个 class 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));
}
这是未定义的行为。
显示的代码不会尝试初始化 class 变量。它尝试将 memmove
() 放到 class 指针上,并假定 class 的大小为 2*sizeof(int)+sizeof(float)
。 C++ 标准不保证这一点。
此外,所示代码还假定传递给构造函数的参数布局与此 POD
成员的布局相同。这同样不是 C++ 标准指定的。
使用 memmove
初始化单个 class 成员是安全的。例如,以下是安全的:
foo::foo(int x_,int y_,float z_)
{
memmove(&x, &x_, sizeof(x));
memmove(&y, &y_, sizeof(y));
memmove(&z, &z_, sizeof(z));
}
当然,这没有任何用处,但这样是安全的。
不,这不安全,因为根据标准,由于 alignment/padding,不能保证成员 立即 紧随其后。
更新后,情况更糟,因为传递参数的位置及其顺序使用起来不安全。
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. - Donald Knuth
您不应该尝试优化您不确定是否需要的代码。我建议您在能够执行此类优化之前 分析您的代码。这样,您不会浪费时间提高某些代码的性能,不会影响应用程序的整体性能。
通常,编译器足够聪明,可以猜测您要对代码做什么,并生成保持相同功能的高效代码。为此,您应该确保启用编译器优化(-Olevel
标记或通过编译器命令参数切换单个优化)。
例如,我看到一些编译器将 std::copy
转换为 memcpy,当编译器确定这样做很简单时(例如数据是连续的)。
不,这不安全。这是未定义的行为。
和代码
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)
{ }
使用 memmove/memcpy 初始化带有构造函数参数的对象是否安全?
好像没有人用过这个方法,但是我试了一下效果很好。
在堆栈中传递的参数会导致问题吗?
假设我有一个 class 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));
}
这是未定义的行为。
显示的代码不会尝试初始化 class 变量。它尝试将 memmove
() 放到 class 指针上,并假定 class 的大小为 2*sizeof(int)+sizeof(float)
。 C++ 标准不保证这一点。
此外,所示代码还假定传递给构造函数的参数布局与此 POD
成员的布局相同。这同样不是 C++ 标准指定的。
使用 memmove
初始化单个 class 成员是安全的。例如,以下是安全的:
foo::foo(int x_,int y_,float z_)
{
memmove(&x, &x_, sizeof(x));
memmove(&y, &y_, sizeof(y));
memmove(&z, &z_, sizeof(z));
}
当然,这没有任何用处,但这样是安全的。
不,这不安全,因为根据标准,由于 alignment/padding,不能保证成员 立即 紧随其后。 更新后,情况更糟,因为传递参数的位置及其顺序使用起来不安全。
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. - Donald Knuth
您不应该尝试优化您不确定是否需要的代码。我建议您在能够执行此类优化之前 分析您的代码。这样,您不会浪费时间提高某些代码的性能,不会影响应用程序的整体性能。
通常,编译器足够聪明,可以猜测您要对代码做什么,并生成保持相同功能的高效代码。为此,您应该确保启用编译器优化(-Olevel
标记或通过编译器命令参数切换单个优化)。
例如,我看到一些编译器将 std::copy
转换为 memcpy,当编译器确定这样做很简单时(例如数据是连续的)。
不,这不安全。这是未定义的行为。
和代码
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)
{ }