In this case, your settings struct and the object you want to construct with those settings share the same lifetime: the duration of a call to theFunction
. So the best option is probably the simplest one: don't even bother giving them separate variables in the first place. In modern C++, that could be as concise as:
MyClass mClass({ /* struct arguments */ });
Not only is this more concise, but it's potentially more efficient. Because the struct is an unnamed temporary, it only lives for the duration of this constructor call, which means at least in theory it can safely be moved into the mClass
constructor rather than copied.
Also, you should make your MyClass constructor take the settings struct by reference (const reference if possible). Doing pass by value usually forces a copy, which seems completely unnecessary in this case.
In general, it might not be this simple, and the various questions you add on at the end imply you want slightly more general advice.
I don't know the proper design for this sort of message passing in C++ I am not used to manual memory management coming from a managed language background. What is the standard way to handle this struct full of settings?
The big thing to realize is that in modern C++, you should almost never manage memory manually. In particular, you almost always want to use stack-allocated variables or smart-pointers to heap-allocated variables instead of "raw" pointers, and you almost always want to work with classes that implement RAII (i.e., they have destructors which properly clean up after themselves) instead of relying on "naked" new/delete pairs.
In particular, if you don't need mClass
to be a pointer (either raw or smart), then don't make it one.
MyClass mClass; // doesn't get any simpler than this
If you really need it to be a pointer, then use a smart pointer to ensure it gets cleaned up correctly no matter what happens.
// the `auto` is deduced to be `std::unique_ptr<MyClass>`
auto mClass = std::make_unique<MyClass>(MyStruct{ /* struct arguments */ });
Your go-to smart pointer should be std::unique_ptr
since that (usually) has zero runtime overhead compared to a raw pointer, it enforces unique ownership by not allowing you to copy it (which is usually what you want), and it can be easily converted to other smart pointers like std::shared_ptr
if you need more complicated behavior.
Both of these options guarantee the mClass
object will be destroyed and deallocated even in the face of exceptions or early returns. You never have to write an explicit "please destroy this now" anywhere in your code.
I highly recommend reading Effective Modern C++ for more details on these issues.
Or maybe instead or initializing the struct on the stack I just do a heap allocation and clean up the struct in the class destructor.
This is entirely possible, but overly complicated and kinda pointless.