Main Content

Reference to un-named temporary

Local reference is declared by using unnamed temporary variable that a function returns by value

Since R2023a

Description

This defect occurs when:

  1. A function returns an object by value.

  2. You declare a local reference by using the returned unnamed temporary object.

Consider this code:

std::string get();
const std::string &s = get();
The function get() returns a string by value. The local reference s is declared by using the unnamed temporary string. Polyspace® reports a defect.

Risk

Returning an object by copy and then declaring a local reference by using the returned copy can lead to unexpected behavior. For instance, If you later update the code to return the temporary object by reference, perhaps to improve performance, the local reference then resolves to a nonlocal object instead of a local copy. Modifying the nonlocal object causes unexpected results. See Local Reference Declared by Using Unnamed Returned-by-Value Temporary Object.

This defect can lead to inefficiencies in cases where it is possible to use the unnamed temporary object directly instead of using a reference to the temporary object. See Local Reference Used for Passing Object to Function.

Fix

To fix this defect, capture the returned unnamed temporary object by using a variable instead of a reference. When possible, use the unnamed temporary object directly.

Examples

expand all

In this example, the function f.getname() returns an unnamed temporary std::string object by value. The function func declares the local reference s by using this temporary string object. Polyspace reports a defect.

#include<string>
class myString
{
    public:
        myString(const std::string &s): m_name(s) {}

        std::string getName() const { return m_name; }
        void setName(const std::string &s) { m_name = s; }

    private:
        std::string m_name;
};

void func()
{
    myString f("Brian");

    const std::string &s = f.getName(); 

    f.setName("Bob");
    assert(s == "Brian"); //Succeeds
}
Suppose that to improve efficiency, you update the function myString::getname to return an std::string object by reference. Then, the reference s resolves to the string myString::m_name instead of a copy of the string. If your code relies on the fact that s is a copy of myString::m_name, then the code might produce unexpected results after the change to myString::getname. For instance, in the preceding code, s contains Brian, but in the following code, s contains Bob, which causes the assert() statement to fail.
#include<string>
class myString
{
    public:
        myString(const std::string &s): m_name(s) {}

        //Updated getname() for improved performance

        const std::string &getName() const { return m_name; } 
        void setName(const std::string &s) { m_name = s; }

    private:
        std::string m_name;
};
void func()
{
    myString f("Brian");

    const std::string &s = f.getName(); 

    f.setName("Bob");
    assert(s == "Brian");//Fails!
}

Correction — Avoid Using Local References to Store Returned-by-Value Objects

To fix this defect, capture the returned-by-value temporary string in a variable instead of a reference.

#include<string>
class myString
{
    public:
        myString(const std::string &s): m_name(s) {}

        std::string getName() const { return m_name; }
        void setName(const std::string &s) { m_name = s; }

    private:
        std::string m_name;
};

void func()
{
    myString f("Brian");

    const std::string s = f.getName(); //No defect

    f.setName("Bob");
    assert(s == "Brian"); //Succeeds
}
The assert statement succeeds if myString::getname is later changed to return an std::string by reference.

In some cases, it is more efficient to use the unnamed temporary object directly instead of capturing the object in a reference. For instance, in this code, Polyspace reports a defect.

#include<string>
extern       std::string  getSByValue();
extern void useString(std::string s);

void func()
{
    const std::string &s = getSByValue();
    useString(s);
}

Correction — Use Unnamed Temporary Directly

To fix this issue, use the unnamed temporary object directly when calling useString(). In this case, capturing the temporary object is unnecessary.

#include<string>
extern       std::string  getSByValue();
extern void useString(std::string s);

void func()
{
    useString(getSByValue());
}

Result Information

Group: Good practice
Language: C++
Default: Off
Command-Line Syntax: LOCAL_REF_TO_UNNAMED_TEMPORARY
Impact: Low

Version History

Introduced in R2023a