2

I recently realized that I can do this:

void someFunc(const std::string &str)
{
   //content
}

...
someFunc("Hello World"); //this works

I'm wondering how that works and why it works.

Thanks

jmasterx
  • 52,639
  • 96
  • 311
  • 557

6 Answers6

5

It works because std::string has a constructor from const char * that is not marked explicit. The C++ compiler will insert a call to one such constructor (per argument) if necessary to make the arguments match.

zwol
  • 135,547
  • 38
  • 252
  • 361
4

You example actually demonstrates the opposite: a const char array is interpreted as std::string. (BTW, a string literal is not a const char *, it is a const char[N] - a char array, not a char pointer).

The reason it work is that a char array is implicitly convertible to std::string by means of std::strings conversion constructor. The compiler performs the conversion for you, in full agreement with overload resolution rules of C++ language.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    +1 for pointing out that a character literal is NOT a `const char *`. (Actually, it's not a `const char[N]` either -- it's a `char[N]` -- character literals are non-`const` even though they must be treated as `const`...) It amazes me how many programmers get this wrong. – Billy ONeal Dec 24 '10 at 02:47
  • @Billy: Huh? §2.13.4/1: "An ordinary string literal has type “array of n const char”". – GManNickG Dec 24 '10 at 02:58
  • 2
    @Billy ONeal: In this case you happen to be the one who gets it wrong. String literals were `char[N]` arrays in *C* language. C++ is different. In *C++* string literals are `const char[N]` arrays. The reason you can initialize `char *` with string literals in C++ is a dedicated (and deprecated) conversion introduced in C++ specifically for that purpose. (There was no need for such conversion in C). Of course, string literals are non-mutable in both languages. – AnT stands with Russia Dec 24 '10 at 06:14
  • @AndreyT: That's what I meant by "you have to treat them as `const` " -- you're not allowed to modify them but their type is effectively non- `const` as a result of the conversion. It's defined as if the data was `const` in order to take advantage of other parts in the standard which refer to `const` data (namely that you can't modify the data). But the *type` is effectively non- `const`. – Billy ONeal Dec 24 '10 at 06:42
  • @Billy ONeal: Not true. In C++ the type of the string literal is effectively `const`. In order to use the deprecated const-removing conversion you have to deliberately create the circumstances that would invoke that conversion (assign/initialize a `char *` object by a literal). In all other circumstances `const` is preserved. For one example, when you do `throw "Hello!"` an exception of type `const char *` is thrown (not of type `char *`). And this exception will not be caught by a `catch (char *)` clause. For another example, the `char *p = "Hello!" + 1;` initialization will not compile. – AnT stands with Russia Dec 24 '10 at 07:33
  • @AnT if the type in c was non const why was it in read only section . and you cannot change it? – Suraj Jain Dec 27 '16 at 10:16
3

This works because the compiler creates a temporary object of type std::string in the caller, before calling someFunc().

The compiled code will be roughly equivalent to the following:

{
    std::string _temp1("Hello World");
    someFunc(_temp1);
}

(I put the code in braces to show that the _temp1 destructor will be executed immediately after the call to someFunc() returns.)

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
0

This is caused by implicit conversion in C++

Community
  • 1
  • 1
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
0

Your question is backwards... a const char* becomes a std::string when used as an argument, and this is because there is an implicit conversion (a constructor with one argument) from const char* to std::string.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

I think you mean the reverse: 'how are const char*s interpreted as std::strings' ? Well, there is a constructor of the std::string class that converts a const char* into a std::string

An actual constructor can be found in /usr/include/c++/4.3.4/bits/basic_string.h

 /**
  *  @brief  Construct string as copy of a C string.
  *  @param  s  Source C string.
  *  @param  a  Allocator to use (default is default allocator).
  */
  basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
  • Well, that's where the actual constructor is on **your** machine, but that certainly doesn't mean where it is on the OP's machine. My machine, for example, doesn't have a path called `/usr` -- the equivalent would be `C:\Users` -- yet `std::basic_string` certainly exists for me too. – Billy ONeal Dec 24 '10 at 02:46
  • true, but he wanted to understand how it is defined. –  Dec 24 '10 at 04:00