参考的最佳实践

时间:2014-11-25 10:25:22

标签: c++ c++11 reference

只是出于好奇心,教育和澄清的原因,我想问一下我使用参考文献和价值观的方式是不是好的做法。

理论上:

class ComplexGraphicalShape {
...
public:
    void setRasterImageURL(const QString &rasterImageURL);
    const QString &rasterImageURL() const;
...
private:
    const QString *_rasterImageURL;
};

...

void ShadowGram::setRasterImageURL(const QString &rasterImageURL) {
    safeDelete(_rasterImageURL); // handle deletion
    _rasterImageURL = new QString(rasterImageURL);
}

const QString &ShadowGram::rasterImageURL() const{
    // Question 2: Why is it a problem if I return 
              // return "www.url.com/shape_url.jpg"
    return *_rasterImageURL; // that is the right way
}

...

complexGraphicalShape().setRasterImageURL(kURLImagesToShare + imageName);
complexGraphicalShape().setRasterImageURL("www.url.com/url.jpg"); // Question 1.

我的第一个问题是我可以使用在setRasterImageURL functioncall中创建的临时对象引用多长时间?哪个变量存在?(在堆栈中如果我没有弄错,但如果我用另一个临时引用调用另一个函数怎么办。

我的第二个问题是,如果我想使用此return "www.url.com/shape_url.jpg",为什么我在问题2部分中收到警告?那件事情有点类似。我可以使用该临时对象多长时间?

感谢您抽出时间回答和解释

3 个答案:

答案 0 :(得分:3)

Q1:临时字符串与“绑定”它的临时引用一样长。那就是 - 只要你是“内部”setRasterImageURL()函数。这当然包括所有被称为“内部”功能的功能。请注意,将另一个引用存储到此临时字符串 NOT 会延长临时对象的生命周期。

complexGraphicalShape().setRasterImageURL("www.url.com/url.jpg");
// the temporary object is "destroyed" when it goes out of scope, and it's scope is just the called function

Q2:返回的问题是你使用“C string”(字符数组)创建一个临时的QString对象(在堆栈上,仍然在函数内)并返回对该临时值的引用。由于此临时对象在此函数返回后立即销毁,因此您的引用永远无效并引用死对象。另一方面 - 返回对成员变量的引用有效,因为此对象不会被销毁,因此只要主对象存在,引用就是有效的。

const QString &ShadowGram::rasterImageURL() const{
    return "www.url.com/shape_url.jpg"
    // the temporary object is destroyed here, before the function returns, reference is invalid
}

答案 1 :(得分:3)

  1. 临时存在直到setRasterImageURL返回,因此您可以安全地传递对它的引用,但是您需要注意不要保存引用以供日后使用。临时存储在编译器想要的任何地方。该引用最有可能在寄存器或堆栈中传递。

  2. 这是一个问题,因为您正在返回对临时QString对象的引用,并且该函数返回时该对象将被销毁。您根本不允许使用该引用。

  3. 传递参考"向内"一个函数(通常)是安全的,只要你不存储它,同时传递一个引用"向外"从函数中要求您确保在函数返回时引用的对象仍然存在。

答案 2 :(得分:3)

  

我的第一个问题是我可以使用setRasterImageURL功能调用中创建的临时对象引用多长时间?

它不是在函数调用中创建的,它是在调用函数之前在调用者的堆栈上创建的,并在函数返回后被销毁。

  

存在哪个变量?(在堆栈中如果我没有弄错,但是如果我用另一个临时引用调用另一个函数该怎么办。

是的,在堆栈上。函数调用返回后在;处被销毁(在"完整表达式"的末尾)。

  

那件事情有点类似。我可以使用该临时对象多长时间?

直到创建临时的完整表达式结束,即return语句,因此它在函数甚至完成返回之前立即超出范围。这就是您收到警告的原因 - 返回的引用绑定到一个不再存在的对象,并且永远不会安全使用。

这两个案件均由标准中的12.2 [class.temporary]第5段涵盖:

  

- 绑定到函数调用(5.2.2)中的引用参数的临时对象将持续存在,直到包含该调用的完整表达式完成为止。
   - 不延长函数返回语句(6.6.3)中返回值临时绑定的生存期;临时在return语句中的full-expression结束时被销毁。