J'essaie d'enregistrer une copie de char[10] dans l'extrait de code ci-dessous, j'aimerais simplement savoir si c'est la bonne façon d'utiliser std::move et cela enregistrera en fait une copie de {{X2} } en tant qu'objet Struct2 est en cours de construction.

#include <string>
#include <iostream>
#include <cstring>
#include <memory>
using namespace std;


struct Struct1 {
    int a;
    string b;
    char c[10];
};

struct Struct2 {
    const Struct1 struct1;
    int d;
    string e;
};

int main() {
    int a = 10;
    auto b = "b";
    char c[10] = "12345";
    Struct1 struct1{a, b};
    strcpy(struct1.c, c);
    Struct2 str2{std::move(struct1), 10, "e"}; //<-- no copy of struct1.c, right?
    cout << str2.struct1.c << endl;
}

Y a-t-il aussi une meilleure syntaxe dans la construction Struts2, si je ne veux pas copier char[10] deux fois (Struct1 ne sera pas utilisé autrement que comme un champ de Struct2)?

0
tesla1060 18 sept. 2020 à 10:57

3 réponses

Meilleure réponse

Un tableau C a la même sémantique pour le déplacement et la copie. En d'autres termes, une copie et un déplacement d'un tableau C font exactement la même chose.

L'avantage sera sur std::string, par exemple membre Struct1::b.

Et oui, c'est la syntaxe / utilisation correcte de std:: move.

2
bolov 18 sept. 2020 à 08:12

Si vous regardez les variables avec le débogueur, vous pouvez voir que la seule entité déplacée est la chaîne non-POD ("plain old data") b. Avant le déménagement, vous avez: entrez la description de l'image ici

Et après le déménagement, vous avez: entrez la description de l'image ici

Vous verrez que la chaîne 'b' < cycledata a été copiée dans un nouvel emplacement mémoire et l'ancien est effacé mais il a toujours son tampon d'origine à 0x00edfe40

Comme d'autres l'ont dit, std::move est plus préoccupé par le transfert de propriété, en s'assurant que les copies ne sont pas conservées, plus encore qu'en évitant de copier la mémoire en soi.

1
Den-Jason 18 sept. 2020 à 08:40

Au lieu de polluer ma réponse précédente, voici une suggestion:

Si vous souhaitez utiliser unique_ptr, essayez quelque chose comme ceci. Malheureusement, make_unique ne joue pas bien avec les listes d'initialisation, vous devez donc définir un constructeur autre que celui par défaut ( à moins que quelqu'un ne connaisse un moyen de contourner cela? ).

class Struct1
{
public:
    int a;
    string b;
    char c[10];

    Struct1::Struct1(int _a, string const&& _b, char const* _c) : a(_a), b(_b)
    {
        strcpy_s(c, 10, _c);
    }
};

using Struct1_unique = std::unique_ptr<Struct1>;

typedef struct 
{
    Struct1_unique pStruc1;
//  const Struct1 struct1;
    int d;
    string e;
}
tsStruct2;


int main() {
    int a = 10;
    auto b = "b";
    char c[10] = "12345";
    //Struct1 struct1{ a, b };
    Struct1_unique pStruc1 = std::make_unique<Struct1>(a, b, c);
    //strcpy_s(pStruc1->c, 10, c);
    tsStruct2 str2{ std::move(pStruc1), 10, "e" };
    cout << str2.pStruc1->c << endl;
    str2.pStruc1.reset();
}

Donc, encore une fois, avant le déménagement, vous avez: entrez la description de l'image ici

Et après:

enter image description here

Vous pouvez voir que la propriété de l'objet a été transférée (pStruc1 maintenant "vide") sans faire de copie; les pointeurs vers l'objet et les données de chaîne à l'intérieur n'ont pas changé. Le reset à la fin désalloue l'objet.

0
Den-Jason 18 sept. 2020 à 09:10