在超出范围之后传递给构造函数的值会发生什么?

时间:2011-02-21 00:08:30

标签: c++ string object-lifetime

我一直在寻找答案,并没有找到任何与我的问题类似的东西。

我有一个类,我们称之为Foo,在它的构造函数中使用const char*指针。在我的代码中,我需要使用Foo的{​​{1}}作为参数创建一个新的std::string。问题是,一旦字符串超出范围,传递给Foo的值(或指针,这是我感到困惑的地方......)就变得无效。

现在该字符串无效,Foo的.data()无效。

如何将字符串数据的值传递给const char*,以便一旦字符串超出范围,它就不会失效?

5 个答案:

答案 0 :(得分:4)

为什么不直接复制字符串?那样你知道它不会消失。如果你不知道const char *会在你的课程生命周期中出现,你需要复制它(或做一些不同的事情,比如将字符串包装在参考计数器中)

答案 1 :(得分:1)

你应该复制Foo内的字符串来存储它,如果你需要它来经过构造函数的调用范围。

答案 2 :(得分:1)

您有两种选择:

  1. (目前为止更简单的选项)只需将其存储在班级的std::string中即可。
  2. 将您自己的char*new[]strcpy数据分配到构建器中的新char*。然后,您还需要为delete[] Foo的{​​{1}}定义析构函数。然后,与Rule of Three的情况一样,您还需要定义复制构造函数和复制赋值运算符以分配自己的新char*(对于复制赋值运算符{ {1}}旧版char*)并复制原始delete[]中的char*。很容易犯错并造成内存泄漏,或者试图访问释放的内存时随机崩溃。
  3. X

    char*

    我很有可能遗漏了一些东西,因为这是我的头脑,但我相信有人会在评论中指出它。

    另外,使用Boost中的Foo可能会让选项#2的生活更轻松,但我对它没有多少经验,而且对于一个小项目来说可能有点重。

    还有一条评论。您应该使用string.c_str(而不是string.data),因为它会添加您需要的NULL字符。

答案 3 :(得分:0)

仅提供描述无助于破译代码中出现的错误。 std::string::data()返回指向字符数组的起始字符的指针。只要传递的内存位置不会失效,类成员和传递的参数都指向同一位置。如果你看到,传递的参数超出范围(即,它不再有效),那么你的类成员变成一个悬空指针。在这种情况下,最好做一个传递的字符串的副本。这应该给你一个想法 -

#include <iostream>
#include <string>

class Foo
{
    const char* temp;

    public:
    Foo( const char* temp_ ) : temp(temp_) {}
    void check( )
    {
            while( *temp != '\0' ){
                std::cout << *temp ;
                ++temp;
            }
            std::cout << std::endl;
    }
};

int main()
{
    std::string str = "I am a string";

    Foo *obj = new Foo( str.data() );

    obj->check();
    return 0;
}

输出:我是一个字符串
IdeOne。希望这有帮助!

答案 4 :(得分:0)

复制它。在refcount友好语言中,您将“保留”字符串。但这是C ++。如果你不复制它,你有很高的悬挂指针风险。

class Foo
{
 public:
   Foo(const char*  _data) 
   { 
      mData = new char[strlen(_data) + 1];
      strcpy(mData, _data); 
   }
   Foo& operator=(const Foo& _other) { /* deep copy string */ } 
   Foo(const Foo& _other) { /* deep copy string */ }
   ~Foo() { delete[] mData; }
 private:
   char* mData;
};

class Foo
{
 public:
   Foo(const char* _data) : mData(_data) { }
 private:
   std::string mData;
};

class Foo
{
 public:
   Foo(const std::string& _data) : mData(_data) { }
 private:
   std::string mData;
};

如您所见,std::string选项更容易。