Casting this Vector3 into a const char* has worked in implicit and explicit conversions, but hasn't when attempting to convert it at construction time. Only then does const char* 'v3pchar' return blank. Any thoughts? The full code is below. Thanks!
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
struct Vector3 {
int x, y, z = 0;
Vector3() {
cout << "Vector3()" << endl;
};
Vector3(int X, int Y, int Z) : x(X), y(Y), z(Z) {
cout << "Vector3(int X, int Y, int Z)" << endl;
};
// Focal point here
operator const char* () {
cout << "operator const char* called" << endl;
v3string = to_string(x) + ", " + to_string(y) + ", " + to_string(z);
v3pchar = v3string.c_str();
return v3pchar;
}
private:
string v3string = "Never even blank";
const char* v3pchar = "So why does this become blank?";
};
int main() {
Vector3 v1 = Vector3(1, 2, 3);
cout << "Vector3 implicit cast to char*: [" << v1 << "]" << endl; // Works
const char* v2 = v1;
printf("Vector3 explicit cast to char*: [%s]\n", (const char*)v2); // Works
cout << "---------------------------------------------" << endl;
const char* v3 = Vector3(4, 5, 6);
cout << "Vector3 instantiation cast to char*: [" << v3 << "]" << endl; // Empty
return 0;
};
v3pchar = v3string.c_str();
The const char *
pointer returned by c_str()
is owned by its std::string
, and is only valid until the std::string
is modified, or it gets destroyed, whichever comes first. Capsule summary: as soon as v3string
is modified or destroyed, v3pchar
is no longer valid.
const char* v3 = Vector3(4, 5, 6);
This results in the following sequence of events:
Vector3
object gets created and constructed.operator const char*
method gets called, and it returns a const char *
owned by an internal std::string
that's a member of the Vector3
object.const char *
is assigned to v3
.Vector3
object gets destroyed, together with its std::string
member.const char *
pointer is no longer valid, since the std::string
object that owns it is now destroyed.Any subsequent use of this const char *
pointer results in undefined behavior.
It should be possible to modify the shown code, using some features in modern C++ that would result in this construct becoming ill-formed (class method ref qualifiers), and having your C++ compiler catch this common bug. But that would be another question; as far as the reason for your observed results: it's undefined behavior for the reasons outlined above.