Hängt das Verhalten der garantierten Kopierentfernung von der Existenz eines benutzerdefinierten Kopierkonstruktors ab?

Lesezeit: 2 Minuten

Hangt das Verhalten der garantierten Kopierentfernung von der Existenz eines
xskxzr

Der folgende Code verhält sich mit oder ohne benutzerdefinierten Kopierkonstruktor anders unter GCC 8.0.1:

#include <cassert>

struct S {
    int i;
    int *p;
    S() : i(0), p(&i) {}
    // S(const S &s) : i(s.i), p(&i) {}  // #1
    // S(const S &s) : i(s.i), p(s.p) {} // #2
    // S(const S &s) = delete;           // #3
};

S make_S() {return S{};}

int main()
{
    S s = make_S();
    assert(s.p == &s.i);
}

Mit jedem der kommentierten benutzerdefinierten Kopierkonstruktoren (selbst mit Nr. 2, demjenigen, der eine einfache flache Kopie durchführt) schlägt die Assertion nicht fehl, was bedeutet, dass das garantierte Entfernen der Kopie wie erwartet funktioniert.

Ohne einen benutzerdefinierten Kopierkonstruktor schlägt die Assertion jedoch fehl, was das Objekt bedeutet s in main Die Funktion ist nicht standardmäßig konstruiert. Warum passiert das? Funktioniert die garantierte Kopierelision hier nicht?

  • Guaranteed copy elision und RVO sind jedoch nicht ein und dasselbe

    – StoryTeller – Unslander Monica

    20. Februar 18 um 6:38 Uhr

  • Erwähnenswert ist auch, dass es auch auf Clang 7.0.0 fehlschlägt

    – StoryTeller – Unslander Monica

    20. Februar 18 um 6:42 Uhr

  • @StoryTeller RVO erfüllt in diesem Beispiel die Kriterien der garantierten Entfernung von Kopien. Es ist eine Initialisierung von einem Prvalue desselben Klassentyps.

    – xskxzr

    20. Februar 18 um 6:51 Uhr

  • @juanchopanza Es scheint, dass GCC die garantierte Entfernung von Kopien seit Version 7 vollständig unterstützt dieser Tisch

    – xskxzr

    20. Februar 18 um 6:57 Uhr

  • Ich irre mich wahrscheinlich, aber ich kann wirklich nichts Falsches an Ihrem Beispiel finden, das die Kopierentfernung fehlerhaft machen würde. Ich vermute ein QOI-Problem (sowohl für Clang als auch für GCC).

    – StoryTeller – Unslander Monica

    20. Februar 18 um 7:10 Uhr


Hangt das Verhalten der garantierten Kopierentfernung von der Existenz eines
Daniel Langr

Zitat aus C++17 Working Draft §15.2 Temporary Objects Paragraph 3 (https://timsong-cpp.github.io/cppwp/class.temporary#3):

Wenn ein Objekt des Klassentyps X an or übergeben wird von einer Funktion zurückgegeben, wenn jeder Kopierkonstruktor, Bewegungskonstruktor und Destruktor von X entweder trivial oder gelöscht ist und X mindestens einen nicht gelöschten Kopier- oder Bewegungskonstruktor hat, Implementierungen dürfen ein temporäres Objekt zum Halten erstellen der Funktionsparameter bzw Ergebnisobjekt. … [ Note: This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. — end note]

In Ihrem Fall, als ich sowohl das Kopieren als auch das Verschieben von Konstruktoren standardmäßig vorgenommen habe:

S(const S &) = default;
S(S &&) = default;

Assertion schlug auch mit GCC und Clang fehl. Beachten Sie, dass implizit definierte Konstruktoren trivial sind.

.

634290cookie-checkHängt das Verhalten der garantierten Kopierentfernung von der Existenz eines benutzerdefinierten Kopierkonstruktors ab?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy