Return of a permanent facility and construction from temporary

I recently discovered the difference between msvc and g ++ / clang ++ compilers, which are related to the behavior of RVO when a persistent object is returned. A simple example illustrating the difference:

#include <iostream>

class T
{
public:
    T() { std::cout << "T::T()\n"; }
    ~T() { std::cout << "T::~T()\n"; }
    T(const T &t) { std::cout << "T::T(const T&)\n"; }
    T(T &&t) { std::cout << "T::T(T&&)\n"; }
    T(const T &&t) { std::cout << "T::T(const T&&)\n"; }
};

const T getT()
{
    T tmp;
    return tmp;
}

int main()
{
    T nonconst = getT();
}

In optimizations, both examples will only produce T () and ~ T () calls, expected due to RVO (which, incidentally, ignores the return type constant). But without them, the results are different.

clang ++ or g ++ with -fno-elide-constructorsall the rules:

T::T()
T::T(T&&) // from non-const local tmp variable to temp storage (const, due to return-type)
T::~T()
T::T(const T&&) // from constant temp storage to nonconst variable
T::~T()
T::~T()

msvc (2013) ignores the return type constant:

T::T()
T::T(T&&) // from local non-const tmp var to non-const nonconst var
T::~T()
T::~T()

With a little modification:

const T getT()
{
    const T tmp; // here const is added
    return tmp;
}

clang ++ or g ++ c -fno-elide-constructors, all as expected again:

T::T()
T::T(const T&&) // from const local tmp var to temp storage (const, due to return-type)
T::~T()
T::T(const T&&) // from constant temp storage to nonconst variable
T::~T()
T::~T()

msvc (2013):

T::T()
T::T(const T&&) // from local const tmp var to non-const nonconst var
T::~T()
T::~T()

, ( const tmp): , , T(const T &&t) = delete; g++/clang++ : use of deleted function ‘T::T(const T&&)’ msvc .

, - MSVC? ( )

: msvc , g++/clang++ do not.

#include <iostream>

class T
{
public:
    T() { std::cout << "T::T()\n"; }
    ~T() { std::cout << "T::~T()\n"; }
    T(const T &t) { std::cout << "T::T(const T&)\n"; }
    T(T &&t) { std::cout << "T::T(T&&)\n"; }
    T(const T &&t) = delete;
};

const T getT()
{
    const T tmp;
    return tmp;
}

int main()
{
    T nonconst = getT(); // error in gcc/clang; good for msvc
}
+4
1

, const - . :

struct T
{
    T() = default;
    T(T &&) = delete;
};

T getT()
{
    T tmp;
    return tmp;
}

int main()
{
    T x = getT();
}

gcc clang, , . , , - . [class.copy]:

/ , , , , lvalue return (, ) id-, , -- -, , rvalue. , rvalue (, cv), , lvalue. [. , . , , elision , , . -end note]

, , rvalue. T(T&& ), delete d. , .

/ elision - . , , .

+1

Source: https://habr.com/ru/post/1608070/


All Articles