0

So I recently installed CLion and after some setup I started messing with some older code I'd written. Now a great thing about CLion is that it helps you with coding style etc. but one thing I found strange is that it recommended to me to split the definition and assignment of variables. I remember a specific case where I defined strings as follows:

string path = "mypath";

But the IDE recommended to write it like:

string path;
path = "mypath";

Now I started looking for this online to find pros and cons of both methods. Apparently the former is faster but the latter is more secure because it calls the copy constructor or something (I didn't quite understand that part). My question is basically: Since CLion recommends doing it the latter way, does that mean that it is always better? Is there one way that is preferred over the other or is it situational? Do they each have their pros/cons and if so, what are they?

Any help or reliable resources are greatly appreciated.

Thanks in advance, Xentro

Xentro
  • 35
  • 1
  • 7
  • 1
    this advice makes no sense whatsoever. Ofcourse `string path = "mypath";` should be proffered. – bolov Oct 27 '17 at 17:26

4 Answers4

1

Your IDE needs to be consigned to the bin.

string path = "mypath"; is an infinitely better pattern. This is because, in general, there is no potential hazard of an indeterminate value of path. (Granted, in this case, that is not an issue since a std::string has a well-defined default constructor but the preferred way is a good habit to get into).

The compiler is also spared the headache of constructing then assigning a value to an object.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

But the IDE recommended to write it like:

string path;
path = "mypath";

Time to uninstall the IDE. The recommendation is utter nonsense.

Perhaps the worst thing about it is how it prevents const correctness. If path never changes, then you should make it const, and you can only do that if you initialise the variable with the correct value right away:

std::string const path = "mypath";

Note that depending on the context of the code, you may also want to use auto (which will turn the variable into a char pointer, because the deduced type of "mypath" is a char array, but perhaps it turns out you don't even need a full-fletched std::string?) - and that also only works if you do not follow the stupid IDE recommendation:

auto const path = "mypath";

Apparently the former is faster

Nonsense. This is not about speed but about correctness and code maintainability.

but the latter is more secure because it calls the copy constructor or something (I didn't quite understand that part).

That's nonsense, too. It calls one of std::string's overloaded assignment operators, not the copy constructor. And it's not more "secure" in any usual sense of the word.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
1

The advice is nonsense and other answers here tell that already.

I want to add a source for this: Straight from the creator of C++ Bjarne Stroustrup and the chairman on C++ comete (hope I don't get his postion wrong) Herb Sutter:

C++ core guidelines:

ES.20: Always initialize an object

Reason Avoid used-before-set errors and their associated undefined behavior. Avoid problems with comprehension of complex initialization. Simplify refactoring. Example

void use(int arg)
{
    int i;   // bad: uninitialized variable
    // ...
    i = 7;   // initialize i
}

No, i = 7 does not initialize i; it assigns to it. Also, i can be read in the ... part. Better:

void use(int arg)   // OK
{
    int i = 7;   // OK: initialized
    string s;    // OK: default initialized
    // ...
}

Note The always initialize rule is deliberately stronger than the an object must be set before used language rule. The latter, more relaxed rule, catches the technical bugs, but:

  • It leads to less readable code
  • It encourages people to declare names in greater than necessary scopes
  • It leads to harder to read code
  • It leads to logic bugs by encouraging complex code
  • It hampers refactoring

The always initialize rule is a style rule aimed to improve maintainability as well as a rule protecting against used-before-set errors.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • So it says it's OK to initialize a string this way? – Xentro Oct 27 '17 at 18:30
  • @Xentro it's ok in the sense that is `s` is not uninitialized as in the case of `i`. It is OK if you want a default constructed (empty) string. But not if what you want is a `std::string` initialized to a certain string value. – bolov Oct 27 '17 at 18:46
  • Ok so why is int i not initialized but string s is? Is it because string has more overhead and a more complex implementation? – Xentro Oct 27 '17 at 18:52
  • these are the language rules. Mostly legacy reasons. – bolov Oct 27 '17 at 19:22
0
string path = "mypath";

The code above is called using a copy constructor

string path;
path = "mypath";

And the other one is called uses the assignment operator.

Theoretically, the pros and cons really depend on how the compiler going to deal with the code. So it vary from compiler to compiler. In general, the first way is trying to build a object by copying another existing object. While the second one is first create a new empty object, then using the assignment operator ("=", the equal mark) to give value to the variable.

You can see more discussions in the following links: Why separate variable definition and initialization in C++? and What's the difference between assignment operator and copy constructor?

n4feng
  • 2,226
  • 3
  • 11
  • 17