在结构内动态分配的数组

时间:2017-08-03 19:16:38

标签: c++ arrays struct

我正在学习在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 个答案:

答案 0 :(得分: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;