myMemberString = "";
This one falls under one of the somewhat quirky parts of the language. This specific case invokes the constructor that accepts a char* parameter and the default allocator parameter.
When an object is created and immediately assigned, and when the constructor also takes a parameter of a compatible type, a near-universal early optimization was to just call the constructor rather than both the constructor and the assignment.
When the language was standardized back in 1998, that optimization was codified and turned into a requirement, and it remains in the standard today. It is under the section called a converting constructor, partially covered under the 'copy initialization' blanket, and has some interesting rules due to its history. The rule of how and when the constructor is used directly versus when the assignment operator is used can also be modified by the 'explicit' keyword.
cppreference has this little gem explaining it, which applies in this case:
struct A
{
A(int) { } // converting constructor
A(int, int) { } // converting constructor (C++11)
...
};
...
A a1 = 1; // OK: copy-initialization selects A::A(int)
A a2(2); // OK: direct-initialization selects A::A(int)
A a3 {4, 5}; // OK: direct-list-initialization selects A::A(int, int)
A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
A a5 = (A)1; // OK: explicit cast performs static_cast
As that list hopefully makes clear, each of these options calls the constructor even though several of them appear to use the assignment operation.
For booleans I know it's tricky, they will not be default 'false' in 100% of the cases, so I initialize them in the contructor with 'false' explicitly.
And how about pointers? (which I currently always initialize to 'nullptr' in the constructor)
The rules are consistent, so if it doesn't happen in 100% of the cases then you probably don't understand the rules.
Both bools and pointers must be initialized in your code. The rules about what gets initialized to zero (also meaning false)
are described here. Pointers may be statically initialized, such as the line:
char* ptr = "Hello, World!"; where the pointer is automatically initialized to point to a piece of static data.
If those rules for static initialization and zero initialization don't apply, initializer lists work, as does direct initialization, copy initialization, default member initialization, and on brand new compilers, differed dynamic initialization. There are plenty of options available to you, but you do need to ensure it is initialized to a value before it is used, otherwise the results are "undefined".
It is further complicated by the fact that modern major operating systems zero out your memory when it is assigned to the process as a security measure. It wouldn't be secure to hand out uninitialized memory that happened to have whatever was left around from other programs, such as usernames and passwords and bank account balances, and there were many viruses and Trojan horses in the 1980s that exploited the security vulnerability. So if you get a freshly allocated block of memory from the OS you might happen to have it zeroed out even though it didn't meet the zero initialization requirements.
Bool is also quirky with undefined values: "Using a bool value in ways described by this International Standard as “undefined,” such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false". While in practice it should evaluate based on whatever happened to be in that memory block at the time, the standard allows for additional undefined behavior.
Take some time to read up on the rules of initialization. Then make sure you always initialize your variables using one of those rules.