简体   繁体   English

最佳做法与参考

[英]Best practices with references

Only for curiosity and educating and clarification reasons I would like to ask that the way I use references and values are good practices or not. 仅出于好奇,教育和澄清的原因,我想问一下我使用参考和价值观的方式是否是好的做法。

Theoretically: 理论上:

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.

My first question is that how long can I use the temporary object reference which is created inside setRasterImageURL functioncall? 我的第一个问题是,我可以使用setRasterImageURL函数调用内部创建的临时对象引用多长时间? Where exist that variable?(in the stack If I am not mistaken, but what if I call another function with that temporary reference. 该变量在哪里?(如果没有记错,则在堆栈中,但是如果我使用该临时引用调用另一个函数,该怎么办?

My second question is that why I got a warning in Question 2 section if I would like to use this return "www.url.com/shape_url.jpg" ? 我的第二个问题是,如果我想使用此return "www.url.com/shape_url.jpg" ,为什么在问题2部分得到警告? That thing is kind of similar. 那东西有点相似。 How long can I use that temporary object? 我可以使用该临时对象多长时间?

Thanks for your time for the answer and explanations 感谢您的时间来回答和解释

Q1: The temporary string exists as long as the temporary reference that is "bound" to it. Q1:临时字符串存在只要与它绑定的临时引用。 That is - as long as you are "inside" setRasterImageURL() function. 那就是-只要您在setRasterImageURL()函数的“内部” setRasterImageURL() This - of course - includes all functions called "within" this function. 当然-这包括所有称为“此功能内”的功能。 Note that storing another reference to this temporary string does NOT prolong the lifetime of the temporary object. 请注意,存储对该临时字符串的另一个引用不会延长临时对象的寿命。

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: The problem with returning is that you use "C string" (array of characters) to create a temporary QString object (on stack, still inside the function) and return reference to that temporary. Q2:返回的问题是您使用“ C字符串”(字符数组)创建一个临时QString对象(在堆栈上,仍在函数内部)并返回对该临时对象的引用。 As this temporary object is destroyed right after this function returns, your reference is never valid and refers to a dead object. 由于此函数返回后立即销毁了该临时对象,因此您的引用永远无效,并且引用了死对象。 On the other hand - returning a reference to a member variable works, because this object is not destroyed, so the reference is valid as long as your main object lives. 另一方面,返回对成员变量的引用是可行的,因为该对象未销毁,因此只要您的主对象存在,该引用就有效。

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. The temporary exists until setRasterImageURL returns, so you can safely pass a reference to it along, but you need to be careful not to save the reference for later. 临时存在,直到setRasterImageURL返回,所以您可以安全地传递对其的引用,但是您需要注意不要保存该引用供以后使用。 The temporary is stored wherever the compiler wants to. 临时文件存储在编译器想要存储的任何位置。 The reference is most likely passed either in a register or on the stack. 该引用很可能在寄存器或堆栈中传递。

  2. It is a problem because you're returning a reference to a temporary QString object, and that object is destroyed when the function returns. 这是一个问题,因为您要返回对临时QString对象的引用,并且该对象在函数返回时被破坏。 You're not allowed to use the reference at all. 您根本无法使用参考。

Passing a reference "inwards" to a function is (usually) safe as long as you don't store it, while passing a reference "outwards" from a function requires you to make sure that the referenced object still exists when the function returns. 只要不存储对函数的引用“向内”(通常)是安全的,而从函数中对引用进行“向外”传递则需要您确保函数返回时所引用的对象仍然存在。

My first question is that how long can I use the temporary object reference which is created inside setRasterImageURL functioncall? 我的第一个问题是,我可以使用setRasterImageURL函数调用内部创建的临时对象引用多长时间?

It's not created inside the function call, it's created on the caller's stack before the function is called, and is destroyed after the function returns. 它不是在函数调用内部创建的,而是在调用函数之前在调用者的堆栈上创建的,并在函数返回后销毁。

Where exist that variable?(in the stack If I am not mistaken, but what if I call another function with that temporary reference. 该变量在哪里?(如果没有记错,则在堆栈中,但是如果我使用该临时引用调用另一个函数,该怎么办?

Yes, on the stack. 是的,在堆栈上。 It is destroyed at the ; 它被摧毁; after the function call returns (at the end of the "full expression"). 函数调用返回后(在“完整表达式”的末尾)。

That thing is kind of similar. 那东西有点相似。 How long can I use that temporary object? 我可以使用该临时对象多长时间?

Until the end of the full expression that creates the temporary, which is the return statement, so it goes out of scope immediately before the function has even finished returning . 直到创建临时语句的完整表达式(即return语句)的末尾为止, 因此在函数甚至还没有完成 return它就超出了范围 That's why you get a warning - the returned reference is bound to an object which no longer exists, and is never safe to use. 这就是为什么您会收到警告的原因-返回的引用已绑定到一个不再存在的对象,并且永远无法安全使用。

Both these cases are covered by 12.2 [class.temporary] paragraph 5 in the standard: 标准中的12.2 [class.temporary]第5段涵盖了这两种情况:

— A temporary object bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call. —绑定到函数调用(5.2.2)中的参考参数的临时对象一直存在,直到包含该调用的完整表达式完成。
— The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; —函数返回语句(6.6.3)中临时绑定到返回值的生存期; the temporary is destroyed at the end of the full-expression in the return statement. 临时在return语句中的全表达式结束时销毁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM