Home > Software engineering >  Copy data from shared_ptr to struct
Copy data from shared_ptr to struct

Time:12-09

I've a setup where I need to exchange data provided in structs between two modules .

Module 1 provides data in a shared_ptr of a struct, while module 2 needs data in a "normal" struct.

Code:

#include <iostream>
#include <memory>
#include <cstring>

struct MyStruct1 {
 int x;
 double y;
 long long z;
};

struct MyStruct2 {
 int x;
 double y;
 long long z;
};

int main() {

  auto one = std::shared_ptr<MyStruct1>(new MyStruct1());

  MyStruct2 two;

  one->x = 10;
  one->y = 3.141;
  one->z = 1e9;

  std::cout << "Size of one: " << sizeof(one) << "\n";    // Size of one: 16
  std::cout << "Size of *one: " << sizeof(*one) << "\n";  // Size of *one: 24
  std::cout << "Size of two: " << sizeof(two) << "\n";    // Size of two: 24

  memcpy(&two, &(*one), sizeof(two));

  std::cout << "two.x: " << two.x << "\n";  // two.x: 10
  std::cout << "two.y: " << two.y << "\n";  // two.y: 3.141
  std::cout << "two.z: " << two.z << "\n";  // two.z: 1000000000

  return 0;
}

My project setup guarantees that both structs are defined exactly the same. Therefore, I make use of memcpy.

Since one is a (shared) pointer I tried to use it directly in the command

memcpy(&two, one, sizeof(two));

which results in the error no suitable conversion function from std::shared_ptr<MyStruct1>" to "const void *" exists.

As you see, I circumvent this by de-referincing and then making a normal pointer. While this seems to work, it looks like a hard misuse.

Therefore, I'd kindly ask for your advice on how to copy data properly in this setup.

  • Is there a better way than memcpy?
  • How to address source and target properly?
  • What needs to be considered in terms of efficiency (speed, memory usage)?

This is a simplified example. In real application, module 1 is a ros2 message callback, which has an interface like void topic_callback(const pck::msg::msg1::SharedPtr msg) const Additionally, the structs in my real application are nested with huge number of elements. I do have an assertion, which double-checks that size of source and target are actually the same

CodePudding user response:

By using same type for different objects assignment operator overloading can also copy content from one object to the other. I know you are trying to copy different types, maybe operator overloading for each type can be beneficial. By the way be aware of precision lost by copying elements for example first element of MyStruct1 can be float and the second type maybe integer.

Actually, my considiration here is copying obejcts of two different types can be tedious and error prone in the future even if size of two types are same.

After an update, here the solution i found. With this way you also check the types of other members.

struct MyStruct1 {
     int x;
     double y;
     long long z;

     MyStruct1& operator=(const MyStruct2& a) {
        x = a.x;
        y = a.y;
        z = a.z;
       return *this;
     }
  };

Note: :Since second type should be treated first it should be located above the first data type like:

struct MyStruct2 {
   float x;
   double y;
   long long z;
};

struct MyStruct1 {
   float x;
   double y;
   long long z;

   MyStruct1& operator=(const MyStruct2& a)
   {
      x = a.x;
      y = a.y;
      z = a.z;

      return *this;
   }
};

And the usage of the assignment look as simple as like that in the main:

two = *one;

instead of this

memcpy(&two, &(*one), sizeof(two));
  • Related