#include <iostream>
#include <string>
void foo(const std::string & s)
{
std::cout << s;
}
const char * text = "something";
int main()
{
foo( text );
}
I started wondering what is happening here because gdb
reports s == ""
. What is supposed to happen according to a recent (say C++17
) version of the standard?
Via https://godbolt.org/
I can see an std::string
c-tor, so perhaps one is constructed and passed by reference, then destroyed upon function termination.
The class template std::basic_string
has implicit conversion constructor
basic_string(const charT* s, const Allocator& a = Allocator());
So in this call
foo( text );
a temporary object of the type std::string
is created and a reference to it is used as an initializer of the function parameter. At the end of this statement the temporary object is destroyed.
Here is a demonstrative program that shows what is happening under the hood using a sample class.
#include <iostream>
class String
{
private:
const char *s;
public:
String( const char *s ) :s( s )
{
std::cout << "String( const char * ) is called\n";
}
~String()
{
std::cout << "~String() is called\n";
}
friend std::ostream & operator <<( std::ostream &os, const String & s )
{
return os << s.s;
}
};
void foo( const String & s )
{
std::cout << s << '\n';
}
const char * text = "something";
int main()
{
foo( text );
}
The program output is
String( const char * ) is called
something
~String() is called
The program will not work if the constructor would be declared with the function specifier explicit
.
explicit String( const char *s ) :s( s )
{
std::cout << "String( const char * ) is called\n";
}
To make the program to work you will need to call the constructor explicitly. For example
foo( String( text ) );