[英]converting std::string to const char * and function calls
我的类中有多个需要const char *的方法,因此我在类的构造函数中将字符串转换为const char *并将其存储在const char *类型的本地变量中。 局部变量在构造函数内部有效。 但是,当我在同一类的方法上调用它时,它为空。
如果我使用const引用传递它,我的问题就解决了,但是我希望我的代码在不使用const引用的情况下也能正常工作。
我遵循了如何将std :: string转换为const char *或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();
}
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 ++程序中的各种对象何时被销毁,以及出于何种原因; 以及由此带来的后果。 在这里,结果是指向对象内部内容的保存指针自动失效。 指针的后续使用会产生不确定的结果。
最好使用这个:
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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.