C ++难以将对象添加到数组中

时间:2015-01-29 02:48:24

标签: c++ arrays

我的目标是编写一个函数,将AccountInfo类的对象添加到200个元素的AccountInfo对象数组中。数组开始时没有任何对象。 AccountInfo类包含几个字段 - 主要是char *,有几个整数。

经过数小时的尝试,我无法弄清楚出了什么问题。我的代码都符合,但我得到了一个异常

Project1.exe中0x00A164B0处的第一次机会异常:0xC0000005:访问冲突写入位置0x00000000。

在以下一行:

getAccounts()[size()] = AccountInfo(*newUser);

我尽可能地简化了我的代码,同时保留了基本信息。如果提供AccountInfo类的代码会有所帮助,我也可以这样做。

#include <iostream>
using namespace std;

class AccountInfo
{
private:
    char* _userLoginName;   
    char* _password;        
    unsigned int _uid;      
    unsigned int _gid;      
    char* _gecos;           
    char* _home;            
    char* _shell;           

public:
    //Constructor and Destructor
    AccountInfo(char* username);
    ~AccountInfo();

    //Also contains getters and setters.
};

//Method Definitions

AccountInfo::AccountInfo(char* username)
{
    //Initialize the username and other mandatory fields.
    _userLoginName = username;
    _home = "/", "h", "o", "m", "e", "/", username;
    _shell = "/bin/bash";
}

AccountInfo::~AccountInfo()
{
    //Delete dynamically created fields.
    delete _userLoginName;
    delete _password;               
    delete _gecos;          
    delete _home;           
    delete _shell;
}

class UserDB
{
private:
    AccountInfo* _accounts[200];    
    unsigned int _size;             
    unsigned int _nextUid;          
    unsigned int _defaultGid;       

    AccountInfo* getAccounts();

public:
    UserDB();
    ~UserDB();

    void adduser(AccountInfo* newUser); 

    int size(); // return the number of accounts stored (_size)
};

AccountInfo* UserDB::getAccounts()
{
    return _accounts[200];
}

UserDB::UserDB()
{
    _size = 0;
    _nextUid = 1001;
    _defaultGid = 1001;
}

int UserDB::size()
{
return _size;
}

void UserDB::adduser(AccountInfo* newUser)
{
    getAccounts()[size()] = AccountInfo(*newUser);
}

int main() //main method
{
    UserDB users;
    AccountInfo *x = new AccountInfo("Joe"); 
    //This creates an AccountInfo object with one of its
    //char* fields initialized to "Joe".
    users.adduser(x);

    return 0;
}

我做错了什么?我该如何解决?

5 个答案:

答案 0 :(得分:2)

您正在创建一个新的临时对象,以添加指向:

的指针
getAccounts()[size()] = AccountInfo(*newUser);

为什么要解除引用newUser,只复制构造一个临时的?

你可能想要:

getAccounts()[size()] = newUser;

此外,size并不是该功能的一个很好的名称 - 它使得它听起来好像您每次都在为N+1位置编制索引。 numAccounts或类似的可能更合适。

不要忘记增加此计数器,并检查您是否达不到200限制!

此外,通过添加的代码,我看到您尝试将char*类型的变量设置为"something"。你只能在初始化时这样做;你的构造函数需要在初始化列表中以这种方式设置_shell等,而不是在构造函数体中:

AccountInfo::AccountInfo(char* newUser) : _shell("/bin/bash") {/**/}

答案 1 :(得分:1)

无法以权威方式回答您的问题,因为您没有显示size()和getAccounts()方法的内容。

但可以做出一个很好的猜测:

void UserDB::adduser(AccountInfo* newUser)
{
    getAccounts()[size()] = AccountInfo(*newUser);
}

要使此代码起作用,getAccounts()方法必须返回指向已初始化的AccountInfo对象的现有数组的指针,此代码将使用新构造的对象替换数组中AccountInfo对象的现有实例。

这并没有多大意义。

此外:

AccountInfo* _accounts[200];

这声明了一个200个元素的指向AccountInfo对象的指针数组。这不会声明一个包含200个AccountInfo对象的数组。

我怀疑你的getAccounts()方法以某种方式返回_accounts类成员。如果是这样,这不可能以这种方式工作。至少,除非构造函数在堆上动态分配实际数组,否则将所有这些指针初始化为指向动态分配数组中的相应元素,然后始终返回第零个类实例的地址。

这是它的作用吗?

答案 2 :(得分:0)

AccountInfo* _accounts[200]; 

由于_accounts[index of element]未使用NEW创建,因此_accounts[index of element]为NULL。 请在getAccounts()[size()]

之前检查NULL getAccounts()[size()] = AccountInfo(*newUser);

答案 3 :(得分:0)

AccountInfo* UserDB::getAccounts()
{
    // This returns a pointer to the element as index 200,
    // which is past the end of the array and 'undefined behavior'
    return _accounts[200];
}

由于您声明了一个200 AccountInfo 指针的数组(即,不是200 AccountInfo 对象的数组),您应该返回指向该成员的指针。

AccountInfo** UserDB::getAccounts()
{
    return _accounts;
}

此外,假设 addUser 函数旨在取得给定指针的所有权,则应更新如下:

void UserDB::adduser(AccountInfo* newUser)
{
    // This function also needs to guard against size() returning
    // values larger than 199 and increment the size

    // This takes ownership of the pointer and the destructor needs
    // to delete the memory (see 'rule of three' below)
    getAccounts()[size()] = newUser;
}

此外,由于这是C ++,您应该使用标准容器或智能指针来处理此内存管理。例如:

  • 的std ::矢量
  • std :: array C ++ 11
  • std :: unique_ptr C ++ 11

此外,如果 UserDB 类实际上是拥有 AccountInfo 指针,那么您应该知道rule of three

如果C ++ 11可用,那么你也可以实现移动语义。

答案 4 :(得分:0)

即使这个问题已经两年了,我想提一个没有人提出过的答案。 在我看来,如果可能的话,你应该使用boost :: static_vector(http://www.boost.org/doc/libs/1_64_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.static_vector)。它具有您的代码尝试具有的相同行为。它构造一个具有固定数量元素的静态数组,并提供与std :: vector相同的接口。如果你尝试推送的元素多于可能,它就像std :: vector一样抛出一个out_of_memory异常。