as you can probably guess from the title, I want to understand what exactly happens when a std::string is passed to a function as a const reference, because earlier today I ran into a few situations I didn't quite understand entirely. Here's some code:
#include <string> #include <stdio.h> struct Interface { virtual void String1(const std::string &s) = 0; virtual void String2(const std::string &s) = 0; virtual void DoSomething() = 0; }; struct SomeClass : public Interface { void String1(const std::string &s) override { s1 = s.c_str(); } void String2(const std::string &s) override { s2 = s.c_str(); } void DoSomething() override { printf("%s - %s\n", s1, s2); } private: const char *s1, *s2; }; struct AnotherClass { AnotherClass(Interface *interface) : interface(interface) { this->interface->String1("Mean string literal"); } void DoTheThing() { std::string s("Friendlich string literal"); interface->String2(s); interface->DoSomething(); } private: Interface *interface = nullptr; }; int main(int argc, char **argv) { SomeClass some_class; AnotherClass another_class(&some_class); another_class.DoTheThing(); } When using const char * for s1 and s2 in SomeClass the program prints Friendlich string literal - Friendlich string literal or [some rubbish] - Friendlich string literal instead of Mean string literal - Friendlich string literal as I was expecting.
When switching to std::string for s1 and s2 it works as expected, printing Mean string literal - Friendlich string literal.
What a coworker and I are guessing is that the string in the ctor of AnotherClass goes out of scope but SomeClass still has the address of the string stored because of c_str().
When using std::string instead of const char * for s1 and s2 it actually makes a copy, so going out of scope isn't a problem. Like this:
struct SomeClass : public Interface { void String1(const std::string &s) override { s1 = s; } void String2(const std::string &s) override { s2 = s; } void DoSomething() override { printf("%s - %s\n", s1.c_str(), s2.c_str()); } private: std::string s1, s2; }; So... what's really happening? Why doesn't it work with const char *? Why does it work with std::string?