我一直在寻找答案,并没有找到任何与我的问题类似的东西。
我有一个类,我们称之为Foo
,在它的构造函数中使用const char*
指针。在我的代码中,我需要使用Foo
的{{1}}作为参数创建一个新的std::string
。问题是,一旦字符串超出范围,传递给Foo的值(或指针,这是我感到困惑的地方......)就变得无效。
现在该字符串无效,Foo的.data()
无效。
如何将字符串数据的值传递给const char*
,以便一旦字符串超出范围,它就不会失效?
答案 0 :(得分:4)
为什么不直接复制字符串?那样你知道它不会消失。如果你不知道const char *会在你的课程生命周期中出现,你需要复制它(或做一些不同的事情,比如将字符串包装在参考计数器中)
答案 1 :(得分:1)
你应该复制Foo
内的字符串来存储它,如果你需要它来经过构造函数的调用范围。
答案 2 :(得分:1)
您有两种选择:
std::string
中即可。char*
与new[]
和strcpy
数据分配到构建器中的新char*
。然后,您还需要为delete[]
Foo
的{{1}}定义析构函数。然后,与Rule of Three的情况一样,您还需要定义复制构造函数和复制赋值运算符以分配自己的新char*
(对于复制赋值运算符{ {1}}旧版char*
)并复制原始delete[]
中的char*
。很容易犯错并造成内存泄漏,或者试图访问释放的内存时随机崩溃。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
选项更容易。