Volker Weißmann
Volker Weißmann

Reputation: 574

C++ in-place class instantiation

Take a lot at this (working) code

class MyClass {
public:
  double data[6];
  double func() const {
      return data[1] + 2*data[3];
  }
};

double takeMyClassReference(const MyClass &obj) {
    return obj.func();
}

void construct(const double y[]) {
    const MyClass *obj = reinterpret_cast<const MyClass *>(y);
    double val = takeMyClassReference(*obj);
    // do something with val
}

this code does what I want and it is efficient, the start of construct was translated to

movsd   24(%rdi), %xmm0
addsd   %xmm0, %xmm0
addsd   8(%rdi), %xmm0

which is as efficient as it gets.

Is it possible to write this in a safer way, without a reinterpret_cast, but without sacrificing speed? I cannot change the signature of construct or takeMyClassReference.

Upvotes: 1

Views: 276

Answers (2)

Volker Wei&#223;mann
Volker Wei&#223;mann

Reputation: 574

If you're willing to move from MyClass owning the data, to MyClass not owning the data.

class MyClass {
public:
  double *data;
  double func() const {
      return data[1] + 2*data[3];
  }
};
void construct(double y[]) {
    MyClass obj;
    obj.data = y;
    double val = takeMyClassReference(obj);
    // do something with val
}

Upvotes: 1

Davis Herring
Davis Herring

Reputation: 39778

The only allowed way of doing this is with std::memcpy:

void construct(const double y[]) {
    MyClass x;
    std::memcpy(&x,y,sizeof x);
    double val = takeMyClassReference(x);
    // do something with val
}

Clang already optimizes this perfectly; ICC comes close (but misses the strength reduction of using addition), while GCC generates useless stack stores (including one after the math, oddly).

Upvotes: 2

Related Questions