2015-10-27 28 views
1

当我正在阅读我的C++书籍并编写一些示例时,出现了一个问题。是否声明一个私有字符串作为参考有所作为?

... 
private: 
    const string someString; 

public: 
    MyClass(const string& someString) : someString(someString) {} 
    const string& getSomeString() const { return someString; } 
... 

是否声明someString作为参考实际上有区别?

... 
private: 
    const string& someString; 

public: 
    MyClass(const string& someString) : someString(someString) {} 
    const string& getSomeString() const { return someString; } 
... 

如果是这样,有什么优点/缺点或用例(因为这两个例子编译好)?

回答

4

后者很容易导致悬空引用,因为它只是指向一些不受你的类控制的对象。所以我会避免这种情况。 (和往常一样,除非你有一个很好的理由。)

另外一个显着的区别:在第二种情况下,在你的类字符串“将改变”,如果使用的字符串来构建它,因为你只引用它。这在第一种情况下不会发生,因为您拥有自己的字符串副本。

1

构造函数中引用的字符串来自类外部。只要原始字符串有效,引用成员才有效。考虑下面这个例子:

MyClass *p; 
{ 
    string temp = "hello"; 
    p = new MyClass(temp); 
} 
cout << p->getSomeString(); // reference to destroyed object 

这段代码是错误的,因为它是在类中提到的字符串temp不再存在。

这个问题可以更微妙地表现出来。

const char *text = "Hello"; 
MyClass c(text); 
cout << c.getSomeString(); // reference to destroyed object 

这段代码也是错误的,因为在构造函数调用中创建的临时std::string对象由下一行的时间不再存在。

1

如果您将someString声明为const string,它将包含在构造函数中传递给它的值。

然而,someString是一个const string&,它拥有其保存在某个地方的类之外的字符串,该类不能保证在未来的任何一点仍然会存在,所以你应该避免这种情况的地址一。

0

如果someString不应该是一个观察者,那么通过存储一个引用,你意味着错误的语义。我会避免这一点。

Otoh,如果它应该是一个观察者,那么你显然必须存储一个引用。

+0

你是什么意思的“观察员”? –

+0

仅供参考。如果引用的对象发生变化,观察者会反映这一点。 – emlai

+0

观察者不能使用指针吗? –

3

如果你想要一个你自己的字符串,不要存储对其他人的字符串的引用。

在第二种情况下,该字符串的寿命你存储的引用,必须超过您存放在对象的。

例如,

MyClass instance("bad"); 

会离开成员中悬而未决的参考。

您还可以在距离不太致命的,但混乱的幽灵行动:

std::string s = "Hello"; 
MyClass instance(s); 
s = "World"; 
std::cout << instance.getSomeString(); // Prints 'World' 

基准部件是很少一个很好的解决方案,以我的经验。

相关问题