将std :: string转换为const char *和函数调用

时间:2016-12-27 02:03:00

标签: c++ string function c++11 pointers

我的类中有多个方法需要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();
}

2 个答案:

答案 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();
    }