我的类中有多个方法需要const char *所以我在我的类的构造函数中将字符串转换为const char *并将其存储在类型为const char *的局部变量中。局部变量在构造函数中有效。但是,当我在同一个类的方法上调用它时它是空的。
如果我使用const引用传递它我的问题是固定的但我希望我的代码可以在不使用const引用的情况下工作。
我跟着How to convert a std::string to const char* or char*?寻找其他方法将字符串转换为const char *。我认为c_str()正确转换字符串。
我想了解导致我的局部变量为空的根本原因。 我为我的问题编写了示例代码。
有问题的代码:
#include <iostream>
#include <string>
using namespace std;
class Config{
string strFileName_ = "/path/filename.ext";
public:
string getFileName() {return strFileName_;}
};
class Loader{
const char * className_;
public:
Loader(string name){
//className_ = name.c_str(); //same result with .data()
className_ = name.data();
cout << "[inside Loader constructor]className_ is:" << className_ << endl;
}
void loadFile(){
cout << "[inside loadFile] className_ is:" << className_ << endl;
}
};
int main(){
Config cfg;
Loader ld(cfg.getFileName());
ld.loadFile();
}
使用字符串而不是const char *的代码没有此问题。 正如我所解释的,如果我使用const引用,问题就不再存在了。 参考代码:
#include <iostream>
#include <string>
using namespace std;
class Config{
string strFileName_ = "/path/filename.ext";
public:
const string &getFileName() {return strFileName_;}
};
class Loader{
const char * className_;
public:
Loader(const string& name) {
className_ = name.c_str();
cout << "[inside Loader constructor]className_ is:" << className_ << endl;
}
void loadFile(){
cout << "[inside loadFile] className_ is:" << className_ << endl;
}
};
int main(){
Config cfg;
Loader ld(cfg.getFileName());
ld.loadFile();
}
答案 0 :(得分:4)
Loader(string name){
//className_ = name.c_str(); //same result with .data()
className_ = name.data();
“根本原因”是c_str()
或data()
返回的指针指向std::string
拥有的数据。当std::string
被破坏时,指针不再有效。没了。它的内容不复存在。加入合唱团看不见。去见它的制造商了。这是一个前指针。
这里,string name
是按值传递给构造函数的参数。当构造函数返回时,此参数将被销毁。通过c_str()
或data()
保存的指向其内容的指针不再是有效指针。
对象的范围和生命周期是C ++的一个关键的基本原则。您必须完全了解何时以及如何创建或销毁各种对象。与其他语言(如Java)不同,C ++不会为您管理此问题。您必须了解C ++程序中的各种对象何时被销毁,以及出于何种原因;以及由此产生的后果。这里,结果是保存的指向对象内部内容的指针自动失效。随后使用指针会产生不确定的结果。
答案 1 :(得分:1)
更好地使用它:
class Config{
string strFileName_ = "/path/filename.ext";
public:
string getFileName() { return strFileName_; }
};
class Loader{
string className_;
public:
Loader(string name){
//className_ = name.c_str(); //same result with .data()
className_ = name.data();
cout << "[inside Loader constructor]className_ is:" << className_ << endl;
}
void loadFile(){
cout << "[inside loadFile] className_ is:" << className_ << endl;
}
};
int main(){
Config cfg;
Loader ld(cfg.getFileName());
ld.loadFile();
}
否则,如果你真的想玩指针:
class Config{
string strFileName_ = "/path/filename.ext";
public:
string getFileName() { return strFileName_; }
};
class Loader{
char *className_;
public:
Loader(string name){
className_ = new char[name.size() + 1];
std::copy(name.begin(), name.end(), className_);
className_[name.size()] = '\0'; // don't forget the terminating 0
cout << "[inside Loader constructor]className_ is:" << className_ << endl;
}
void loadFile(){
cout << "[inside loadFile] className_ is:" << className_ << endl;
delete []className_;
}
};
int main(){
Config cfg;
Loader ld(cfg.getFileName());
ld.loadFile();
}