Piszę ogólny interfejs do języków skryptowych i potrzebuję połączenia funkcji, które zwracają obiekt i umieścić wynikowy obiekt w przestrzeni dostarczonej przez język skryptowy. Przetestowałem z Clang ++ w systemie Mac OS, a poniższe wydają się wykonać kopię / ruch:

class T {
public:
    T() {}
    T(const T &t) {
        std::cout << "Copy" << std::endl;
    }
    T(T&&t) : x(t.x) {
        std::cout << "Move" << std::endl;
    }
private:
    int x = 3;
};

T h()
{
    return T();
}

void buildTInto(void *p)
{
    new (p) T(h());
}

int main(int argc, char *argv[])
{
    alignas(T) char space[sizeof(T)];
    buildTInto(space);
}

Uruchamianie tego kodu niczego nie drukuje. Czytanie Opis odniesienia CPP Wydaje się, że jest to właściwe zachowanie , Biorąc pod uwagę przykład, który daje tylko jeden konstruktor:

T x = T(T(f())); // only one call to default constructor of T, to initialize x

Myślę, że mój kod jest bardzo podobny jak bez kopiowania, konstruktor ruchu zostałby nazywany (tak jak T(T(f())) zadzwoniłby do dwóch konstrukcji ruchu).

Nie bycie specyfikacyjnym prawnikiem, jestem ciekawy, jeśli moje zrozumienie jest poprawne i zastanawiam się, czy wszystkie kompilatory C ++ 17 robią to poprawnie?

2
Michel 21 marzec 2020, 21:23

1 odpowiedź

Najlepsza odpowiedź

Gwarantowane ELION (AKA: C ++ 17. Definicja prvalues) dotyczy inicjalizacji jakichkolwiek Obiekt typu T z prvalue tego samego typu. Obejmuje obiekty utworzone przez new wyrażeń, w tym umieszczenie formularzy new.

Rzeczywiście, nawet nie musisz powtarzać typu w punkcie wywołania wyrażenia new: new(p) auto(h()); zapewnia obowiązek zobowiązania dla zagwarantowanej elizacji.

1
Nicol Bolas 21 marzec 2020, 20:25