2017-08-03 21 views
-4

私はC++でのメモリの動的割り当てについて学んでいます。私は答えが見つからないような問題に遭遇しました。私のプログラムで構造体内に動的に割り当てられた配列

、私はこのように書きstructています

int numberOfUsers = 5; 
User *usersInformation = new User[numberOfUsers]; 

そしてそれ:、私はこのような何かを行くユーザーの配列を、私のプログラムで

struct Friend 
{ 
    string name = ""; 
    int daysSinceContact = 0; 
}; 

struct User 
{ 
    string name = ""; 
    string password = ""; 
    int numberOfFriends = 0; 
    Friend *friends = new Friend[numberOfFriends]; 
}; 

作成正常に動作します。しかし、私は、たとえば、選択したユーザーにもっとたくさんの友達を追加できるようにしたいと思います:

int nFriends = usersInformation[0].numberOfFriends; 
usersInformation[0].numberOfFriends++; 
usersInformation[0].friends[nFriends-1].name = "John"; 
usersInformation[0].friends[nFriends-1].daysSinceContact = 2; 

私は、私は友人についての情報を含む配列から情報をコピーするために、バッファを使用する必要があることを推測していると

delete[] usersInformation[0].friends[]; 
usersInformation[0].numberOfFriends++; 
usersInformation[0].friends = new Friend[numberOfFriends]; 

これをコピーして新しい友達の情報を追加します。しかし、私が試したとき、それは動作しませんでした。

ヒントはありますか?

+1

変更STD 'へ'フレンド* '::ベクトル'とあなたの問題を持っているが、すべての真のかもしれません – CoryKramer

+0

を解決しました私はまだベクトルについて読んでいないので。たぶん私は自分が持っているツールではできないことをしようとしているだけかもしれません。 –

+0

あなたはダイナミックな配列ではっきり言っていることを確実にすることができますが、 'new'ing、' delete'ing、そしてコピーが正しく行われていることを確認するために多くの手帳を取るでしょう。 – CoryKramer

答えて

1

正しいソリューションは、例えば、代わりにSTLのstd::vectorコンテナを使用して、まったくマニュアルの配列を使用しないことです。

#include <vector> 
#include <string> 

struct Friend 
{ 
    std::string name = ""; 
    int daysSinceContact = 0; 
}; 

struct User 
{ 
    std::string name = ""; 
    std::string password = ""; 
    std::vector<Friend> friends; 
}; 

... 

std::vector<User> usersInformation(5); 

... 

Friend newFriend; 
newFriend.name = "John"; 
newFriend.daysSinceContact = 2; 
usersInformation[0].friends.push_back(newFriend); 

// Or simpler: 
usersInformation[0].friends.emplace_back(Friend{"John", 2}); 

あなたが本当に手動で配列を管理したい場合は、言われていること

#include <string> 

struct Friend 
{ 
    std::string name = ""; 
    int daysSinceContact = 0; 
}; 

struct User 
{ 
    std::string name = ""; 
    std::string password = ""; 
    int numberOfFriends = 0; 
    Friend *friends = new Friend[numberOfFriends]; 

    // default constructor (nothing extra that isn't already done above) 
    User() = default; 

    // copy constructor 
    User(const User &src) : 
     name(src.name), 
     password(src.password), 
     numberOfFriends(src.numberOfFriends), 
     friends(new Friend[numberOfFriends]) 
    { 
     for(int i = 0; i < numberOfFriends; ++i) 
      friends[i] = src.friends[i]; 
    } 

    // move constructor 
    User(User &&src) : 
     name(std::move(src.name)), 
     password(std::move(src.password)), 
     numberOfFriends(numberOfFriends), 
     friends(src.friends) 
    { 
     src.friends = nullptr; 
     src.numberOfFriends = 0; 
    } 

    // destructor 
    ~User() 
    { 
     delete[] friends; 
    } 

    // copy assignment operator 
    User& operator=(const User &src) 
    { 
     if (this != &src) 
     { 
      Friend *newFriends = new Friend[src.numberOfFriends]; 
      for(int i = 0; i < src.numberOfFriends; ++i) 
       newFriends[i] = src.friends[i]; 

      name = src.name; 
      password = src.password; 

      delete[] friends; 
      friends = newFriends; 
      numberOfFriends = src.numberOfFriends; 
     } 

     return *this; 
    } 

    // move assignment operator 
    User& operator=(User &&src) 
    { 
     name := std::move(src.name); 
     password = std::move(src.password); 

     Friend *oldFriends = friends; 
     friends = src.friends; 
     src.friends = oldFriends; 

     int oldNumber = numberOfFriends; 
     numberOfFriends = src.numberOfFriends; 
     src.numberOfFriends = oldNumber; 

     return *this; 
    } 

    // addition helper 
    void addFriend(const std::string &name, int daysSinceContact = 0) 
    { 
     Friend *newFriends = new Friend[numberOfFriends + 1]; 
     for(int i < 0; i < numberOfFriends; ++i) 
      newFriends[i] = friends[i]; 

     newFriends[numberOfFriends].name = name; 
     newFriends[numberOfFriends].daysSinceContact = daysSinceContact; 

     delete[] friends; 
     friends = newFriends; 
     ++numberOfFriends; 
    } 
}; 

またはこの、という点で少し安全です:(破損防止にRule of Fiveを実装含まれており、メモリリーク)の代わりにこのようなより多くの何かをする必要がありメモリ管理:

#include <string> 
#include <utility> 
#include <algorithm> 

struct Friend 
{ 
    std::string name = ""; 
    int daysSinceContact = 0; 
}; 

struct User 
{ 
    std::string name = ""; 
    std::string password = ""; 
    int numberOfFriends = 0; 
    Friend *friends = new Friend[numberOfFriends]; 

    // default constructor (nothing extra that isn't already done above) 
    User() = default; 

    // initializing constructor 
    User(int initialCapacity) : 
     friends(new Friend[initialCapacity]) 
    { 
    } 

    // copy constructor 
    User(const User &src) : 
     User(src.numberOfFriends), 
     name(src.name), 
     password(src.password), 
     numberOfFriends(src.numberOfFriends) 
    { 
     std::copy(src.friends, src.friends + src.numberOfFriends, friends); 
    } 

    // move constructor 
    User(User &&src) : 
     name(std::move(src.name)), 
     password(std::move(src.password)), 
     numberOfFriends(0), 
     friends(nullptr) 
    { 
     std::swap(friends, src.friends); 
     std::swap(numberOfFriends, src.numberOfFriends); 
    } 

    // destructor 
    ~User() 
    { 
     delete[] friends; 
    } 

    // copy assignment operator 
    User& operator=(const User &src) 
    { 
     if (this != &src) 
      User(src).swap(*this); 

     return *this; 
    } 

    // move assignment operator 
    User& operator=(User &&src) 
    { 
     src.swap(*this); 
     return *this; 
    } 

    // swap helper 
    void swap(User &other) 
    { 
     std::swap(name, other.name); 
     std::swap(password, other.password); 
     std::swap(numberOfFriends, other.numberOfFriends); 
     std::swap(friends, other.friends); 
    } 

    // addition helper 
    void addFriend(const std::string &name, int daysSinceContact = 0) 
    { 
     User temp(numberOfFriends + 1); 

     std::copy(friends, friends + numberOfFriends, temp.friends); 
     temp.friends[numberOfFriends] = Friend{name, daysSinceContact}; 

     std::swap(friends, temp.friends); 
     ++numberOfFriends; 
    } 
}; 

いずれかの方法で、あなたがこれを行うことができます。

User *usersInformation = new User[5]; 

... 

usersInformation[0].addFriend("John", 2); 

... 

delete[] usersInformation; 
+0

ありがとう!これは本当に便利で面白いです。あなたの努力のためにありがとう!:) –

+0

こんにちは@RafałMyśliwczykもしあなたの質問が解決されたら、チェックマークをクリックして[受諾する](https://meta.stackexchange.com/q/5234/179419)と考えてください。これは、あなたが解決策を見つけ出し、回答者とあなた自身の両方に評判を与えていることを広範なコミュニティに示します。 –

関連する問題