'How to copy a cstring to a member variable in a constructors initializer list?

Instead of doing it this way:

myClass::myClass(char* name) :
    name(nullptr)
{
this->name = new char[strlen(name) + 1];
    strcpy(this->name, name);
}

How can I initialize name completely inside of the initializer list?



Solution 1:[1]

Since we're dealing with exercises in futility:

myClass::myClass(char* name): name_{
  [](char* n) {
    auto ret = new char[strlen(n) + 1]; 
    strcpy(ret, n);
    return ret;
  }(name)
} {}

Solution 2:[2]

The following may be interesting to you. I wondered what the Joint Strike Fighter (JSF) Air Vehicle C++ Coding Standards document had to say about this, so I checked:

(UNCLASS)

"AV Rule 74:

Initialization of nonstatic class members will be performed through the member initialization list rather than through assignment in the body of a constructor. See Meyers [6], item 12.

Exception:

Assignment should be used when an initial value cannot be represented by a simple expression (e.g. initialization of array values), or when a name must be introduced before it can be initialized (e.g. value received via an input stream).

See AV Rule 74 in Appendix A for details."

(/UNCLASS)

Now, the JSF spec is a product of its time-- circa 2005, for the revision I looked at-- but prior to the newer C++ language variants, this was the best thinking on the matter. (The Meyers reference in question is "Effective C++", for example.)

While the newer language standards provide more options, it can be kind of infuriating getting people who really know those specs to listen to you when you ask how they apply to non-"std::*" types, and more often than not you're talking about C-style, null-terminated strings. Their response tends to be, "don't do that".

Unfortunately, in the embedded systems world and a number of other places, std::array, std::string, etc., still suffer from significant to severe performance problems with any number of vendor-specific toolchains, and occasionally having no choice but to attempt to find a compromise that uses modern C++ best practices on older C data types is something that, as of 2022, absolutely still occurs.

For my own C-string uses cases, I typically use the initializer list to zero the entire target array, and then strncpy (note the N!) in the function body. This is because I often have to go to a little extra trouble to make sure all the memory I'm using is thoroughly scrubbed.

(I'll also mention that if you REALLY have to make sure of that, there are replacement memory management libraries that are truly paranoid about it, but you can pay a pretty significant performance penalty, so it's better to learn how to get what you want from your code in the first place. They can, however, sometimes be a decent solution to help shore up ancient codebases you don't have time to retrofit.)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user657267
Solution 2 breakpoint