Skip to content
Menu
CDhistory
CDhistory

Move constructors

Posted on 26 maja, 2021 by admin

A move constructor of class T is a non-template constructor whose first parameter is T&&, const T&&, volatile T&&, or const volatile T&&, and either there are no other parameters, or the rest of the parameters all have default values.

  • Zawartość
  • Składnia
  • Objaśnienie
  • Konstruktor przeniesienia deklarowany niejawnie
  • Usunięty niejawnie zadeklarowany konstruktor move
  • Trywialny konstruktor move
  • Kwalifikowalny konstruktor move
  • Implicitly-defined move constructor
  • Uwagi
  • Przykład
  • Raporty o defektach
  • Zobacz także

Zawartość

  • 1 Składnia
  • 2 Objaśnienie
  • 3 Konstruktor przeniesienia
  • 4 Usunięty konstruktor przeniesienia
  • 5 Trywialny konstruktor przeniesienia
  • 6 Kwalifikowalny konstruktor przeniesienia
  • 7 Konstruktor przeniesienia
  • 7 Konstruktor przeniesienia
  • .defined move constructor
  • 8 Uwagi
  • 9 Przykład
  • 10 Raporty o wadach
  • 11 Zobacz także

Składnia

.

nazwa_klasy ( nazwa_klasy && ) (1) (od C++11)
nazwa_klasy ( nazwa_klasy && ) = domyślna; (2) (od C++11)
class_name ( class_name && ) = delete; (3) (od C++11)

Gdzie class_name musi zawierać nazwę bieżącej klasy (lub bieżącej instancji szablonu klasy) lub, gdy jest zadeklarowana w przestrzeni nazw lub w deklaracji przyjaciela, musi być kwalifikowaną nazwą klasy.

Objaśnienie

1) Typowa deklaracja konstruktora move.
2) Wymuszenie generowania konstruktora move przez kompilator.
3) Unikanie konstruktora implicit move.

Konstruktor move jest zwykle wywoływany, gdy obiekt jest inicjalizowany (przez bezpośrednią inicjalizację lub kopiowanie) z rvalue (xvalue lub prvalue) (do C++17)xvalue (od C++17) tego samego typu, w tym

  • inicjalizacji: T a = std::move(b); lub T a(std::move(b));, gdzie b jest typu T;
  • przekazywanie argumentów funkcji: f(std::move(a));, gdzie a jest typu T, a f jest void f(T t);
  • funkcja return: return a; wewnątrz funkcji takiej jak T f(), gdzie a jest typu T, która ma konstruktor move.

Gdy inicjalizatorem jest prvalue, wywołanie konstruktora move jest często optymalizowane out (do C++17)nigdy nie wykonywane (od C++17), patrz copy elision.

Konstruktory move zazwyczaj „kradną” zasoby posiadane przez argument (np.) zamiast tworzyć ich kopie, i pozostawiają argument w jakimś ważnym, ale w inny sposób nieokreślonym stanie. Na przykład, przejście ze std::string lub ze std::vector może spowodować, że argument pozostanie pusty. Jednakże, nie należy polegać na tym zachowaniu. Dla niektórych typów, takich jak std::unique_ptr, stan przeniesienia jest w pełni określony.

Konstruktor przeniesienia deklarowany niejawnie

Jeśli dla typu klasy (struct, class, lub union) nie przewidziano konstruktorów przeniesienia zdefiniowanych przez użytkownika i wszystkie poniższe są prawdziwe:

  • nie istnieją zadeklarowane przez użytkownika konstruktory kopiowania;
  • nie istnieją zadeklarowane przez użytkownika operatory przypisania kopiowania;
  • nie istnieją zadeklarowane przez użytkownika operatory przypisania przenoszenia;
  • nie istnieje zadeklarowany przez użytkownika destruktor.

także kompilator zadeklaruje konstruktor move jako jawnego inline public członka swojej klasy z podpisem T::T(T&&).

Klasa może mieć wiele konstruktorów move, np. zarówno T::T(const T&&) jak i T::T(T&&). Jeśli występują konstruktory move zdefiniowane przez użytkownika, użytkownik nadal może wymusić wygenerowanie konstruktora move zadeklarowanego niejawnie za pomocą słowa kluczowego default.

Niejawnie zadeklarowany (lub domyślny przy pierwszej deklaracji) konstruktor move ma specyfikację wyjątków opisaną w specyfikacji wyjątków dynamicznych (do C++17)specyfikacja wyjątków (od C++17)

Usunięty niejawnie zadeklarowany konstruktor move

Niejawnie zadeklarowany lub domyślny konstruktor move dla klasy T jest zdefiniowany jako usunięty, jeśli którekolwiek z poniższych jest prawdziwe:

  • T ma niestatycznych członków danych, którzy nie mogą być przeniesieni (mają usunięte, niedostępne lub niejednoznaczne konstruktory move);
  • T ma bezpośrednią lub wirtualną klasę bazową, która nie może być przeniesiona (ma usunięte, niedostępne lub niejednoznaczne konstruktory move);
  • T ma bezpośrednią lub wirtualną klasę bazową z usuniętym lub niedostępnym destruktorem;
  • T jest klasą podobną do unii i ma członka wariantu z nietrywialnym konstruktorem przeniesienia.

Domyślny konstruktor move, który jest usunięty, jest ignorowany przez rozdzielczość przeciążeniową (w przeciwnym razie uniemożliwiłby kopiowanie-inicjalizację z rvalue).

Trywialny konstruktor move

Konstruktor move dla klasy T jest trywialny, jeśli wszystkie z poniższych są prawdziwe:

  • nie jest on dostarczany przez użytkownika (co oznacza, że jest on domyślnie zdefiniowany lub domyślny);
  • T nie ma wirtualnych funkcji członkowskich;
  • T nie ma wirtualnych klas bazowych;
  • konstruktor przeniesienia wybrany dla każdej bezpośredniej bazy T jest trywialny;
  • konstruktor przeniesienia wybrany dla każdego niestatycznego typu klasy (lub tablicy typu klasy) członka T jest trywialny.

Trywialny konstruktor move jest konstruktorem, który wykonuje tę samą czynność, co trywialny konstruktor copy, czyli wykonuje kopię reprezentacji obiektu, jak gdyby przez std::memmove. Wszystkie typy danych zgodne z językiem C (typy POD) są trywialnie ruchome.

Kwalifikowalny konstruktor move

Kwalifikowalny jest konstruktor move, jeśli nie jest usunięty.

(do C++20)

Kwalifikowany konstruktor przenoszenia jest kwalifikowany, jeśli

  • nie jest usunięty, i
  • jego powiązane ograniczenia, jeśli istnieją, są spełnione, i
  • żaden konstruktor przenoszenia z tym samym typem pierwszego parametru nie jest bardziej ograniczony niż on.
(od C++20)

Trywialność kwalifikujących się konstruktorów move określa, czy klasa jest typem implicit-lifetime, i czy klasa jest typem trywialnie kopiowalnym.

Implicitly-defined move constructor

Jeśli implicitly-deklarowany konstruktor move nie jest ani usunięty ani trywialny, jest zdefiniowany (to znaczy, ciało funkcji jest generowane i kompilowane) przez kompilator, jeśli odr-używany lub potrzebny do oceny stałej. Dla typów unii, niejawnie zdefiniowany konstruktor move kopiuje reprezentację obiektu (jak przez std::memmove). Dla typów klasowych nie będących związkami (class i struct), konstruktor move wykonuje pełne przeniesienie baz i niestatycznych członków obiektu, w kolejności ich inicjalizacji, używając bezpośredniej inicjalizacji z argumentem xvalue. Jeśli spełnia to wymagania konstruktora constexpr, wygenerowany konstruktor move jest constexpr.

Uwagi

Aby umożliwić silną gwarancję wyjątków, konstruktory move zdefiniowane przez użytkownika nie powinny rzucać wyjątków. Na przykład, std::vector polega na std::move_if_noexcept, aby wybrać między move i copy, gdy elementy muszą zostać przeniesione.

Jeśli oba konstruktory copy i move są dostarczone i żaden inny konstruktor nie jest wykonalny, rozdzielczość przeciążenia wybiera konstruktor move jeśli argument jest rvalue tego samego typu (xvalue jak wynik std::move lub prvalue jak bezimienna tymczasowa (do C++17)), i wybiera konstruktor copy jeśli argument jest lvalue (nazwany obiekt lub funkcja/operator zwracająca referencję lvalue). Jeśli podany jest tylko konstruktor kopiowania, wszystkie kategorie argumentów wybierają go (tak długo, jak przyjmuje referencję do const, ponieważ rvalues mogą wiązać się z referencjami const), co czyni kopiowanie awaryjnym dla przenoszenia, gdy przenoszenie jest niedostępne.

Konstruktor jest nazywany „konstruktorem przenoszenia”, gdy przyjmuje referencję rvalue jako parametr. Nie jest on zobowiązany do przenoszenia czegokolwiek, klasa nie musi mieć zasobu, który ma być przeniesiony, a 'konstruktor move’ może nie być w stanie przenieść zasobu, jak w dopuszczalnym (ale może nie rozsądnym) przypadku, gdy parametr jest referencją const rvalue (const T&&).

Przykład

Run this code
#include <string>#include <iostream>#include <iomanip>#include <utility> struct A{ std::string s; int k; A() : s("test"), k(-1) { } A(const A& o) : s(o.s), k(o.k) { std::cout << "move failed!\n"; } A(A&& o) noexcept : s(std::move(o.s)), // explicit move of a member of class type k(std::exchange(o.k, 0)) // explicit move of a member of non-class type { }}; A f(A a){ return a;} struct B : A{ std::string s2; int n; // implicit move constructor B::(B&&) // calls A's move constructor // calls s2's move constructor // and makes a bitwise copy of n}; struct C : B{ ~C() { } // destructor prevents implicit move constructor C::(C&&)}; struct D : B{ D() { } ~D() { } // destructor would prevent implicit move constructor D::(D&&) D(D&&) = default; // forces a move constructor anyway}; int main(){ std::cout << "Trying to move A\n"; A a1 = f(A()); // return by value move-constructs the target from the function parameter std::cout << "Before move, a1.s = " << std::quoted(a1.s) << " a1.k = " << a1.k << '\n'; A a2 = std::move(a1); // move-constructs from xvalue std::cout << "After move, a1.s = " << std::quoted(a1.s) << " a1.k = " << a1.k << '\n'; std::cout << "Trying to move B\n"; B b1; std::cout << "Before move, b1.s = " << std::quoted(b1.s) << "\n"; B b2 = std::move(b1); // calls implicit move constructor std::cout << "After move, b1.s = " << std::quoted(b1.s) << "\n"; std::cout << "Trying to move C\n"; C c1; C c2 = std::move(c1); // calls copy constructor std::cout << "Trying to move D\n"; D d1; D d2 = std::move(d1);}

Output:

Trying to move ABefore move, a1.s = "test" a1.k = -1After move, a1.s = "" a1.k = 0Trying to move BBefore move, b1.s = "test"After move, b1.s = ""Trying to move Cmove failed!Trying to move D

Raporty o defektach

Następujące raporty o defektach zmieniających zachowanie zostały zastosowane retroaktywnie do wcześniej opublikowanych standardów C++.

DR Zastosowano do Zachowanie jak opublikowano Poprawne zachowanie
CWG 1402 C++11 usunięto domyślny konstruktor move, który
wywoływałby nietrywialny konstruktor copy;
a defaulted move constructor that is deleted
still participated in overload resolution
allows call to such copy constructor;
został zignorowany w overload resolution
CWG 2094 C++11 lotny podobiekt wykonany z domyślnego
konstruktora move nietrywialny (CWG496)
trywialność nienaruszona

Zobacz także

  • konstruktor konwertujący
  • przypisanie kopiowania
  • konstruktor kopiowania
  • usuwanie kopii
  • konstruktor domyślny
  • destruktor
  • jawna
  • inicjalizacja
    • inicjalizacja agregatu
    • inicjalizacja stała
    • stała inicjalizacja
    • kopia inicjalizacja
    • inicjalizacja domyślna
    • inicjalizacja bezpośrednia
    • inicjalizator listy
    • inicjalizacja listy
    • inicjalizacja referencji
    • inicjalizacja wartości
    • inicjalizacja zera
  • przypisanie przeniesienia
  • new

Dodaj komentarz Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Ostatnie wpisy

  • Acela powraca: NYC lub Boston za 99 dolarów
  • OMIM Entry – # 608363 – CHROMOSOME 22q11.2 DUPLICATION SYNDROME
  • Rodzice Kate Albrecht – Dowiedz się więcej o jej ojcu Chrisie Albrechcie i matce Annie Albrecht
  • Temple Fork Outfitters
  • Burr (powieść)

Archiwa

  • luty 2022
  • styczeń 2022
  • grudzień 2021
  • listopad 2021
  • październik 2021
  • wrzesień 2021
  • sierpień 2021
  • lipiec 2021
  • czerwiec 2021
  • maj 2021
  • kwiecień 2021
  • DeutschDeutsch
  • NederlandsNederlands
  • SvenskaSvenska
  • DanskDansk
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • RomânăRomână
  • PolskiPolski
  • ČeštinaČeština
  • MagyarMagyar
  • SuomiSuomi
  • 日本語日本語
©2022 CDhistory | Powered by WordPress & Superb Themes