只是出于好奇心,教育和澄清的原因,我想问一下我使用参考文献和价值观的方式是不是好的做法。
理论上:
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部分中收到警告?那件事情有点类似。我可以使用该临时对象多长时间?
感谢您抽出时间回答和解释
答案 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)
临时存在直到setRasterImageURL
返回,因此您可以安全地传递对它的引用,但是您需要注意不要保存引用以供日后使用。临时存储在编译器想要的任何地方。该引用最有可能在寄存器或堆栈中传递。
这是一个问题,因为您正在返回对临时QString
对象的引用,并且该函数返回时该对象将被销毁。您根本不允许使用该引用。
传递参考"向内"一个函数(通常)是安全的,只要你不存储它,同时传递一个引用"向外"从函数中要求您确保在函数返回时引用的对象仍然存在。
答案 2 :(得分:3)
我的第一个问题是我可以使用
setRasterImageURL
功能调用中创建的临时对象引用多长时间?
它不是在函数调用中创建的,它是在调用函数之前在调用者的堆栈上创建的,并在函数返回后被销毁。
存在哪个变量?(在堆栈中如果我没有弄错,但是如果我用另一个临时引用调用另一个函数该怎么办。
是的,在堆栈上。函数调用返回后在;
处被销毁(在"完整表达式"的末尾)。
那件事情有点类似。我可以使用该临时对象多长时间?
直到创建临时的完整表达式结束,即return
语句,因此它在函数甚至完成返回之前立即超出范围。这就是您收到警告的原因 - 返回的引用绑定到一个不再存在的对象,并且永远不会安全使用。
这两个案件均由标准中的12.2 [class.temporary]第5段涵盖:
- 绑定到函数调用(5.2.2)中的引用参数的临时对象将持续存在,直到包含该调用的完整表达式完成为止。
- 不延长函数返回语句(6.6.3)中返回值临时绑定的生存期;临时在return语句中的full-expression结束时被销毁。