1

Is it safe to use memmove/memcpy to initialize an object with constructor parameters?
No-one seems to use this method but it works fine when I tried it.
Does parameters being passed in a stack cause problems?

Say I have a class foo as follows,

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

Can I initialize the variables using memmove as follows?

foo::foo(int x,int y,float z)
{
  memmove(this,&x, sizeof(foo));
}
6
  • 4
    Why on earth are you doing this? Makes assumptions. and have code unreadable. Portability is out of the window Commented Sep 24, 2016 at 14:38
  • I'd say it's not. Compiler is free to pass arguments in another order (abi). And anyway, being scalars, the parameters are probably already in registers, and should stay there Commented Sep 24, 2016 at 14:38
  • @RegisPortalez the compiler won't use a register if the address of the variable is taken Commented Sep 24, 2016 at 14:41
  • @EdHeal Just to avoid writing this->x = x repeatedly Commented Sep 24, 2016 at 14:46
  • @M.M: Since the code only takes the address of x, the other parameters could well be passed in registers. All the more reason not to do this (if undefined behavior wasn't convincing enough already). Commented Sep 24, 2016 at 14:58

4 Answers 4

3

This is undefined behavior.

The shown code does not attempt to initialize class variables. It attempts to memmove() onto the class pointer, and assumes that the size of the class is 2*sizeof(int)+sizeof(float). The C++ standard does not guarantee that.

Furthermore, the shown code also assumes the layout of the parameters that are passed to the constructor will be the same layout as the layout of the members of this POD. That, again, is not specified by the C++ standard.

It is safe to use memmove to initialize individual class members. For example, the following is safe:

foo::foo(int x_,int y_,float z_)
{
   memmove(&x, &x_, sizeof(x));
   memmove(&y, &y_, sizeof(y));
   memmove(&z, &z_, sizeof(z));
}

Of course, this does nothing useful, but this would be safe.

Sign up to request clarification or add additional context in comments.

3 Comments

It doesn't matter which word you prefer to use. The answer is the same.
Got it. Didn't know the layout needn't be the same.
@SrinagRao: Add a virtual destructor to your class and calculate the offsetof your class members. x may or may not be at offset 0. With virtual class members it's likely not.
1

No it is not safe, because based on the standard the members are not guaranteed to be immediately right after each other due to alignment/padding. After your update, this is even worse because the location of passed arguments and their order are not safe to use.

Comments

1

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

You should not try to optimize a code you are not sure you need to. I would suggest you to profile your code before you are able to perform this kind of optimizations. This way you don't lose time improving the performance of some code that is not going to impact the overall performance of your application.

Usually, compilers are smart enough to guess what are you trying to do with your code, and generate high efficient code that will keep the same functionality. For that purpose, you should be sure that you are enabling compiler optimizations (-Olevel flag or toggling individual ones through compiler command arguments).

For example, I've seen that some compilers transform std::copy into a memcpy when the compiler is sure that doing so is straightforward (e.g. data is contiguous).

Comments

0

No it is not safe. It is undefined behavior.

And the code

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

is not even saving you any typing compared to using an initializer list

foo::foo(int x,int y,float z) : x(x), y(y), z(z)
{ }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.