将新对象插入存储库会引发错误

Posted

技术标签:

【中文标题】将新对象插入存储库会引发错误【英文标题】:Inserting new Object to Repository throws error 【发布时间】:2019-03-24 14:57:09 【问题描述】:

我已经为它创建了一个对象和一个存储库。 当我尝试将对象插入存储库(使用我创建的插入函数)时,出现编译错误。

我试图插入到存储库中的类

class Payment
private:
    int day;
    int amount;
    char *type;

public:
    Payment();
    Payment(int day, int amount, char *type);
    Payment(const Payment &p);
    ~Payment();

    //getters
    int getDay()const;
    int getAmount()const;
    char* getType()const;

    //setters
    void setDay(int day);
    void setAmount(int amount);
    void setType(char* type);

    //operator
    Payment& operator=(const Payment& other);
    friend ostream& operator<<(ostream &os,const Payment &obj);
;

//copy constructor
Payment::Payment(const Payment & p)
    this->day = p.day;
    this->amount = p.amount;
    if(this->type!=NULL)
        delete[] this->type;
    this->type = new char[strlen(p.type)+1];
    strcpy_s(this->type, strlen(p.type) + 1, p.type);


//assignment operator
Payment& Payment::operator=(const Payment &other) 
    this->day = other.day;
    this->amount = other.amount;
    this->type = new char[strlen(other.type) + 1];
    strcpy_s(this->type, strlen(other.type) + 1, other.type);
    return *this;


//destructor
Payment::~Payment()
    this->day = 0;
    this->amount = 0;
    if (this->type != NULL) 
        delete[]this -> type;
        this->type = NULL;
    



//Repository header
class Repository
private:
    vector<Payment> list;
public:
    Repository();

    int getLength();

    void insert(const Payment& obj);
    void remove(int position);
;

//Repository cpp
Repository::Repository()
    this->list.reserve(10);


//return the size of the list
int Repository::getLength() 
    return this->list.size();


//add payment to list
void Repository::insert(const Payment &obj) 
    this->list.emplace_back(obj);


//remove payment from list
void Repository::remove(int position) 
    this->list.erase(this->list.begin() + position);

在我的主要功能中

char c[] = "some characters";
Payment pay = Payment(7,9,c);
Repository rep = Repository();
rep.insert(pay);

当我运行程序时出现错误“ 表达式:_CrtlsValidHeapPointer(block) "

【问题讨论】:

那不是编译器错误,那是运行时错误。第二,你为什么不用std::string type;?那将解决您的问题。如果不是这样,这是如何实现“3 规则”的重复,即您缺少Payment 的用户定义复制构造函数。 复制构造函数可以解决问题。我完全忘记了。我会试一试,然后回复结果。谢谢您的帮助! ^_^ 请发布实现复制构造函数、赋值运算符和析构函数的代码。这就是问题所在。 std::vector 要求您放置在向量中的类型具有正确的、无错误的复制语义。如果您使用std::string 而不是char *,那么这将不是问题。既然你坚持使用char *,那么现在由你来编写所有这些函数,没有错误。 另外,请参阅the rule of 3。 @PaulMcKenzie 我也创建了复制构造函数,但仍然无法正常工作。我想使用动态分配。这不是比使用std::string 更快吗?你建议我使用std::string,那么什么时候应该使用string,什么时候应该使用char?即使我改变了类型,我也很想知道如何克服这个错误。 【参考方案1】:

由于std::vector 将进行复制,因此std::vector&lt;Payment&gt; 要求Payment 具有正确的复制语义。您的复制构造函数和赋值运算符未正确实现。赋值运算符会导致内存泄漏,因为您未能delete [] 现有内存。

最简单的解决方案是放弃使用char *type; 成员,而直接使用std::string type;。然后Payment 类将自动具有正确的复制语义。


鉴于此,对Payment 课程的更正如下:

#include <algorithm>
//...
Payment::Payment() : day(0), amount(0), type(nullptr) 

Payment::Payment(const Payment & p) : day(p.day), amount(p.amount), type(nullptr)

    if ( p.type )
    
        type = new char[strlen(p.type) + 1];
        strcpy_s(this->type, strlen(p.type) + 1, p.type);
    


// Use the copy/swap idiom    
Payment& Payment::operator=(const Payment &other) 

    Payment temp(other);  // make a temporary copy
    // swap out contents of temporary with this object
    std::swap(temp.day, day);  
    std::swap(temp.amount, amount);
    std::swap(temp.type, type);
    return *this;  
   // when this brace has been reached, the temp copy dies off with the old data

Payment::~Payment()

   delete [] type;

上面在赋值运算符中使用了copy/swap idiom。复制构造函数使用成员初始化列表。

析构函数不需要检查空指针,因为删除空指针是完全有效的。

【讨论】:

【参考方案2】:

现在添加到std::vector 运行良好,没有任何运行时错误(使用@PaulMcKenzie 发布的代码)。我还找到了一个有效的代码示例,其中只有赋值运算符有点不同。 转换为我的代码将是(并且它正在工作):

Payment& Payment::operator=(const Payment &other) 
    if (this != &other) 
        this->setDay(other.day);
        this->setAmount(other.amount);
        this->setType(other.type);
    
    return *this;

感谢您的帮助!现在它工作得很好!我没有从&lt;algorithm&gt; 图书馆学习很多东西,所以我得仔细看看。祝你好运! ^_^

【讨论】:

这是不正确的。您的赋值运算符有内存泄漏。如果您阅读了我的回答,我提到您的旧版本泄漏了内存。在我的回答中std::swap 是有原因的,而不仅仅是为了装饰。再次,请阅读什么是复制/交换以及它的工作原理。

以上是关于将新对象插入存储库会引发错误的主要内容,如果未能解决你的问题,请参考以下文章

将新对象插入数据库时​​出现Swift dynamicCast错误

JPA 未获取数据引发 *** 错误

没有抛出错误,但数据没有插入数据库(PHP PDO)[重复]

在反应烟雾测试期间引发“缺少 cookie 标头或对象”错误(Create-react-app)

MongoDB插入引发重复键错误

Vuex 突变引发错误 - 不要在突变处理程序之外改变 vuex 存储状态