Warum nicht std::move verhindern RVO?

In vielen Fällen, wenn wieder ein lokal von einer Funktion, RVO kicks in. Allerdings dachte ich, dass explizit mit std::move würde zumindest durchzusetzen, sich zu bewegen, wenn RVO nicht passieren, aber, dass die RVO ist noch immer angewendet, wenn möglich. Es scheint jedoch, dass dies nicht der Fall ist.

#include "iostream"

class HeavyWeight
{
public:
    HeavyWeight()
    {
        std::cout << "ctor" << std::endl;
    }

    HeavyWeight(const HeavyWeight& other)
    {
        std::cout << "copy" << std::endl;
    }

    HeavyWeight(HeavyWeight&& other)
    {
        std::cout << "move" << std::endl;
    }
};

HeavyWeight MakeHeavy()
{
    HeavyWeight heavy;
    return heavy;
}

int main()
{
    auto heavy = MakeHeavy();
    return 0;
}

Getestet habe ich diesen code mit VC++11-und GCC-4.71", "debug" und " release-O2) config. Die copy-ctor ist nie genannt. Der move-ctor wird nur aufgerufen, VC++11 im debug-config. Eigentlich scheint alles in Ordnung zu sein mit diesen Compilern insbesondere, aber meines Wissens RVO ist optional.

Allerdings, wenn ich explizit move:

HeavyWeight MakeHeavy()
{
    HeavyWeight heavy;
    return std::move(heavy);
}

der move-ctor ist immer genannt. So versuchen, um es "sicher" macht es noch schlimmer.

Meine Fragen sind:

- Warum std::move verhindern RVO?

- Wann ist es besser, "das beste hoffen" und sich darauf verlassen, RVO, und Wann sollte ich explizit std::move? Oder, in anderen Worten, wie kann ich die compiler-Optimierung die Arbeit machen und noch durchzusetzen bewegen, wenn RVO nicht angewandt wird?

  • Warum machen die Leute immer noch darüber reden, "das beste hoffen" in diesen Tagen? Welche compiler verwenden Sie mit C++11-Unterstützung, kann aber nicht RVO richtig?
  • Copy elision (der Mechanismus hinter RVO) ist nur gestattet, unter bestimmten, strengen Bedingungen. Schreiben std::move verhindert, dass diese Bedingungen nicht eingehalten werden.
  • Und dieser Bedingungen verhindert, indem std::move sind...?
  • std::move verhindert, dass NRVO (benannt RVO). RVO im Allgemeinen nicht betroffen ist (afaik)
  • Können Sie auf eine Referenz skizziert die Gründe, dies zu verhindern? Bewegt elision überhaupt geschehen?
  • NÖ, return std::move(Schwergewicht()); dennoch ruft der move-ctor.
  • Bewegen elision vorkommt, aber nicht, wenn explizit mit std::move. Lustige Sachen.
  • Ich habe nachgedacht, ich war einfach nur Gründliche by doing explizit std::move, statt es scheint, ich habe sabotiert mich! 😉
  • Ich habe nicht gesagt, dass der compiler RVO im std::move Fall. Ich habe nur gesagt, dass Sie nicht tun können NRVO, aber (wie gesagt, afaik) noch tun können RVO. Es ist die Umsetzung abhängig.
  • Du bist nicht allein.
  • Der Umzug kann noch werden erstellte, wenn der compiler kann beweisen, dass Sie nicht das Programm ändern das Verhalten.
  • Der problem Fall ist derjenige, wo der Verhaltensänderung erlaubt ist, nämlich das weglassen copy/move-Konstruktor ruft. Da der test-Fall per definition muss enthalten Nebenwirkungen, Sie beschränkt sich auf Optimierungen, die sich auf copy elision und nach den Regeln spielen.

Schreibe einen Kommentar