Most people when declaring strings in C , or most other languages, do it like so:
std::string example = "example";
However I've seen some code samples where it is done like this:
std::string example("example");
To me it seems like it needlessly obfuscates the code, particularly if there is a using std::string statement hiding somewhere above the declaration in the code making it look like
string example("example");
To some who may be new to the codebase or are coming from other languages it almost looks like it could be a method or a function.
Is there any practical or performance based reason for using the constructor instead of the assignment operator or does it come down to just personal preference?
CodePudding user response:
The practical reason for the second form is that it reflects what actually happens. Your two examples actually - despite their syntactic differences - do exactly the same thing.
They are both calling a constructor which accepts a const char *
to initialise example
with the literal "example"
.
The main difference is the way they are interpreted at times. I've lost count of the number of times I've seen people insist that
std::string example = "example";
does an assignment that calls std::string
s operator=()
function - except that it doesn't.
People who get tired of fielding such claims (and prefer that someone looking at the code can understand what it actually does, wherever possible) therefore sometimes prefer the second form;
std::string example("example");
CodePudding user response:
Sometimes you don't have a choice. Many constructors are explicit (even some of std::string
's constructors) and you can't call it with the type object = value
syntax, and for consistency type object(value)
would be much better. Being explicit prevents mistakes on things like std::vector<char> v = 'c';
or MyString s = 'v';
that doesn't work as one expects
But C 11 introduced the new {}
initializer syntax and most modern coding conventions strongly prefer it, so you should use this instead
std::string example{ "example" }; // good
auto example{ "example"s }; // better
Even ISO CPP's Core C Guidelines suggests that in ES.23: Prefer the {}
initializer syntax
This has the advantage of preventing narrowing, and it works even for in-class initialization
struct foo {
// OK
std::string example1 = { "example" };
std::string example2{ "example" };
std::string example3 = "example";
// Doesn't work
std::string example4("example");
};
To some who may be new to the codebase or are coming from other languages it almost looks like it could be a method or a function.
That's the well-known most vexing parse issue in C . Both std::string example(std::string(someIdentifier))
and string example(string(someIdentifier))
can represent either a function declaration or a variable definition with initialization. If you learn C you have to learn the syntax
In fact most vexing parse is one of the reasons of the introduction to the new {}
initialization form
See also