6

I have the following c++ code:

#include <iostream>
#include <string>

    int main( int argc, char* argv[] )
    {
        const std::string s1 = "ddd";
        std::string s2( std::string( s1 ) );
        std::cout << s2 << std::endl;
    }

The result is: 1 Why? When I use -Wall flag, compiler write warning: the address of ‘std::string s2(std::string)’ will always evaluate as ‘true’

But this code:

#include <iostream>
#include <string>

int main( int argc, char* argv[] )
{
    const std::string s1 = "ddd";
    std::string s2( ( std::string )( s1 ) );
    std::cout << s2 << std::endl;
}

The result: ddd

It's normal result

Cœur
  • 32,421
  • 21
  • 173
  • 232
G-71
  • 3,346
  • 12
  • 43
  • 67
  • 3
    Couldn't you just make the second line `std::string s2(s1);` Why do you need to include the second `std::string`? – rhololkeolke Oct 21 '11 at 17:36
  • 1
    Why create an intermediate copy? Why not `std::string s2 = s1;`? – Oscar Korz Oct 21 '11 at 17:36
  • @Oscar: Your version creates an intermediate default initialized variable and then copies via the copy assignment operator. The correct version without anything intermediate is rho's. – Xeo Oct 21 '11 at 17:41
  • 1
    @OscarKorz I read that, but it seems to me that the most vexing parse would only occur if you include the inner `std::string` as it then interprets `std::string` as a function (like @Xeo explains). But I just tested it and it compiles fine without the inner `std::string`. Seems to me if you leave out the inner type declaration you avoid the problem in the first place. Perhaps I'm not understanding something, or I'm reading too heavily into the example. – rhololkeolke Oct 21 '11 at 17:43
  • 2
    @Xeo: `std::string s2 = s1;` does not use an assignment operator, it uses the copy constructor. – James McNellis Oct 21 '11 at 17:44
  • @rhololkeolke I deleted my comment already because I was wrong. Your line doesn't trigger the most vexing parse. I was hoping I was quick enough that you wouldn't notice. :) – Oscar Korz Oct 21 '11 at 17:45
  • @James: My bad then, nvm me. :) – Xeo Oct 21 '11 at 19:27

1 Answers1

13

Most-vexing-parse.

std::string s2( std::string( s1 ) );

is parsed as the declaration of a "function taking a std::string parameter named s1 and returning a std::string". You then try to print that function, which will first convert it to a function pointer (normal decay/conversion rule). Since the operator<< of std::ostream isn't overloaded for function pointers in general, it will try a conversion to bool, which succeeds, and since the function pointer is nonnull, it's converted to the boolean value true, which is printed as 1.

Change it to

std::string s2( (std::string( s1 )) );

or even better, just

std::string s2( s1 );
Community
  • 1
  • 1
Xeo
  • 123,374
  • 44
  • 277
  • 381
  • 1
    @Oscar: Copy ctor > copy assignment operator. :) – Xeo Oct 21 '11 at 17:39
  • 7
    `std::string s2 = s1;` calls the copy constructor because its a declaration. – Oscar Korz Oct 21 '11 at 17:41
  • 1
    @Oscar: Hm, my bad then. Nvm me. :) – Xeo Oct 21 '11 at 19:27
  • @OscarKorz: Actually, that's a _[definition](http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration/1410632#1410632)_. – sbi Oct 22 '11 at 22:24
  • @OscarKorz: Well, no problem then, just use one whenever you think the other should apply. `:)` – sbi Oct 24 '11 at 07:17