我有以下课程:
class StringHolder
{
public:
StringHolder(std::string& str)
{
m_str = &str;
}
private:
std::string* m_str;
};
并拥有以下字符串对象(str
),大小为1,024KB:
char c = 'a';
unsigned long long limit = 1024 * 1024;
std::stringstream stream;
for(int i = 0; i < limit; i++)
{
stream << c;
}
std::string str = stream.str();
每当我使用字符串初始化StringHolder类时,不会复制该字符串。那是因为我使用了参考文献&amp;指针,但我不确定我是否正确使用它们:\
问题:我是否使用了参考文献&amp;指针正确吗?
答案 0 :(得分:5)
正确的实现应该是
class StringHolder
{
public:
StringHolder(const std::string& str) //note const
: m_str(str){} //use initialization list
private:
std::string m_str; //no need to make it a pointer
};
答案 1 :(得分:1)
假设已知字符串的生命周期比将引用它的对象寿命更长,并且该对象不需要修改字符串,那么您可以对构造函数中的字符串进行常量引用,存储在:
class StringHolder {
std::string const & str;
public:
StringHolder( std::string const & s ) : str(s) {}
};
使用此解决方案,不会复制字符串的内容,但对原始字符串的任何更改都将影响从引用中看到的内容。此外,这不允许您更改构造后引用的字符串。如果您需要重新设置引用,则必须使用指针:
class StringHolder {
std::string const * str;
public:
StringHolder( std::string const & s ) : str(&s) {}
void reset( std::string const & s ) {
str = &s;
}
};
您需要存储指针而不是引用这一事实是一个实现细节,因此您可以(就像我一样)将其隐藏起来,或者您可以更改接口以通过指针获取字符串以使其成为可能更明确(我更喜欢前者,但后者具有自我记录的效果:更清楚的是必须考虑生命周期)。
另请注意,使用如图所示的实现,可以使用临时来初始化/设置字符串,从而导致未定义的行为:临时死亡,引用指向无处。