2017-08-03 177 views
-4

我正在學習有關C++中內存的動態分配。我遇到了一個我似乎無法找到答案的問題。結構內動態分配數組

在我的計劃,我有一個struct這是這樣的:

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

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

在我的計劃,我創建用戶的數組,這是這樣的:

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

它工作正常。不過我倒是希望能夠給更多的朋友加入到選定的用戶,例如:

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

你當然可以用動態數組來做你正在描述的內容,但是爲了確保'新',''刪除'和複製工作正常,你需要花費大量的時間來記錄它。 – 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}); 

話雖這麼說,如果你真的想手動管理陣列,你需要做更多的東西像這樣的,而不是(其中包括實施Rule of Five防止腐敗和內存泄漏):

#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; 
    } 
}; 

還是這個,這方面稍微更安全內存管理:

#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)通過點擊複選標記。這向更廣泛的社區表明,您已經找到了解決方案,併爲答覆者和您自己提供了一些聲譽。 –