我正在为C ++课做一个家庭作业,并遇到一些困难。我的程序是segfaulting由于“使用大小为8的未初始化值”和item :: name()中的“无效读取大小8”,由item :: operator =调用。
#ifndef ITEM_H
#define ITEM_H
const double WEIGHT_DEFAULT = 1.0;
const int ITEM_NAME_LENGTH = 30;
class item {
public:
// Constructors and deconstructor
item();
item(char* nme, double weight);
virtual ~item();
// Copy constructor
item(const item& itm);
// Overload assignment operator
const item& operator=(const item& itm);
// Overload inequality operator
bool operator!=(const item&) const;
// Mutators and accessors
const char* name(void) const;
double weight(void) const;
void weight(double wght);
void name(char* nme);
protected:
private:
char* m_name;
double m_weight;
};
#endif // ITEM_H
以下是我认为存在问题的实施部分:
...
const item& item::operator=(const item& itm)
{
if (strcmp(this->name(), itm.name()) != 0)
{
this->weight(itm.weight());
strcpy(m_name, itm.name());
}
return *this;
}
const char* item::name(void) const {
return m_name;
}
...
正如你所看到的,部分任务是使用c-strings,因此我陷入了凌乱的细节。我对指针和类的理解是,在使用它们时,我们需要实现析构函数,复制构造函数和重载赋值运算符。我已经完成了以上所有工作。我在Stack Overflow上查看了有关复制和交换习惯用法的一些信息,并尝试实现它,但无法使用我的代码。
我的大脑正在疲惫不堪,试图解开我出错的地方。有人可以告诉我我错过了什么吗?
谢谢!
以下是构造函数,析构函数等:
item::item() {
//ctor
m_name = new char[ITEM_NAME_LENGTH];
strncpy(m_name, " ", ITEM_NAME_LENGTH - 1);
this->weight(WEIGHT_DEFAULT);
return;
}
item::item(char* nme, double wght) {
m_name = new char[ITEM_NAME_LENGTH];
strncpy(m_name, nme, ITEM_NAME_LENGTH - 1);
// We want to check for a rational value being
// passed in to weight. In theory, an item has
// to have *some* kind of weight, so we check
// for a weight of 0. If a weight of 0 has been passed in,
// we instead initialize the item's weight to the
// default weight (set in the header file).
if (wght > 0.0) {
this->weight(wght);
} else {
this->weight(WEIGHT_DEFAULT);
}
return;
}
item::~item() {
//dtor
// TODO: We need to clean up any variables here.
delete[] m_name;
}
item::item(const item& itm) {
// copy ctor
this->weight(itm.weight());
strncpy(m_name, itm.name(), ITEM_NAME_LENGTH - 1);
}
const item& item::operator=(const item& itm)
{
if (strcmp(this->name(), itm.name()) != 0)
{
this->weight(itm.weight());
strcpy(m_name, itm.name());
}
return *this;
}
bool item::operator!=(const item& itm) const
{
return (strcmp(m_name, itm.name()) != 0);
}
现在我已经停止尝试动态分配名称c-string,我在重量函数上出现内存错误......
double item::weight(void) const {
return m_weight;
}
void item::weight(double wght)
{
m_weight = wght;
}
答案 0 :(得分:1)
首先,您无需在return;
语句中明确void
。
第二: 创建复制构造函数时,需要分配用于保存该构造函数内存的空间,与常规构造函数的操作方式相同。
在复制构造函数中尝试:
m_name = new char[ITEM_NAME_LENGTH];
编辑:为了完整性,我的“似乎正在工作”的代码是:
#include <stdio.h>
#include <string.h>
const double WEIGHT_DEFAULT = 1.0;
const int ITEM_NAME_LENGTH = 30;
class item {
public:
// Constructors and deconstructor
item();
item(char* nme, double weight);
virtual ~item();
// Copy constructor
item(const item& itm);
// Overload assignment operator
const item& operator=(const item& itm);
// Overload inequality operator
bool operator!=(const item&) const;
// Mutators and accessors
const char* name(void) const;
double weight(void) const;
void weight(double wght);
void name(char* nme);
protected:
private:
char* m_name;
double m_weight;
};
const item& item::operator=(const item& itm)
{
if (strcmp(this->name(), itm.name()) != 0)
{
m_name = new char[ITEM_NAME_LENGTH];
this->weight(itm.weight());
strcpy(m_name, itm.name());
}
return *this;
}
const char* item::name(void) const {
return m_name;
}
double item::weight(void) const {
return m_weight;
}
void item::weight(double wght) {
m_weight = wght;
}
item::item() {
//ctor
m_name = new char[ITEM_NAME_LENGTH];
strncpy(m_name, " ", ITEM_NAME_LENGTH - 1);
this->weight(WEIGHT_DEFAULT);
return;
}
item::item(char* nme, double wght) {
m_name = new char[ITEM_NAME_LENGTH];
strncpy(m_name, nme, ITEM_NAME_LENGTH - 1);
// We want to check for a rational value being
// passed in to weight. In theory, an item has
// to have *some* kind of weight, so we check
// for a weight of 0. If a weight of 0 has been passed in,
// we instead initialize the item's weight to the
// default weight (set in the header file).
if (wght > 0.0) {
this->weight(wght);
} else {
this->weight(WEIGHT_DEFAULT);
}
return;
}
item::~item() {
//dtor
// TODO: We need to clean up any variables here.
delete[] m_name;
}
item::item(const item& itm) {
// copy ctor
this->weight(itm.weight());
m_name = new char[ITEM_NAME_LENGTH];
strncpy(m_name, itm.name(), ITEM_NAME_LENGTH - 1);
}
bool item::operator!=(const item& itm) const
{
return (strcmp(m_name, itm.name()) != 0);
}
int main(int argc, char* argv[])
{
item i("test",2.0);
item b = i;
item c;
item d = c;
return 0;
}
答案 1 :(得分:1)
我想使用std :: string作为练习的一部分,对吧?否则,这就是字符串处理的方法。您可以尝试的另一件事是避免动态分配字符串。相反,只需使用char m_name[ITEM_NAME_LENGTH];
即可。顺便说一句:那是多长?如果它是名称中的最大字符数,则终止NUL需要+1
。
这就是说,还有一件事:在赋值运算符中,你比较if(this != &other)
,即你比较两个对象的地址。重点是避免自我分配,这很容易出错。您的作业检查名称是否不同,然后仅复制名称和重量。如果只有重量不同怎么办?