C++ 动态分配内存,复制构造函数出错

C++ 动态分配内存,复制构造函数出错,c++,memory,constructor,copy,C++,Memory,Constructor,Copy,我有作业要用动态分配的内存。我的教授给了我一些指示。使用它们,我编写了下面的代码。我在随机时间遇到一个错误。有时,在执行复制之前会出现错误。有时它会复制一个对象,而不会复制下一个对象。我不明白我做错了什么 默认构造函数 GroceryItem::GroceryItem() { item_name = new char[strlen("") + 1]; strcpy(item_name, ""); item_price = 0; qty_on_hand = 0;

我有作业要用动态分配的内存。我的教授给了我一些指示。使用它们,我编写了下面的代码。我在随机时间遇到一个错误。有时,在执行复制之前会出现错误。有时它会复制一个对象,而不会复制下一个对象。我不明白我做错了什么

默认构造函数

GroceryItem::GroceryItem()
{
    item_name = new char[strlen("") + 1];
    strcpy(item_name, "");
    item_price = 0;
    qty_on_hand = 0;
    qty_purchased = 0;
};

下面的函数是复制构造函数,我使用它复制两个对象:

GroceryItem::GroceryItem(const GroceryItem& Grocery_in)
{
    item_name = new char[strlen(Grocery_in.item_name) + 1];
    strcpy(item_name, Grocery_in.item_name);
    item_price = Grocery_in.item_price;
    qty_on_hand = Grocery_in.qty_on_hand;
    qty_purchased = Grocery_in.qty_purchased;
}
;
下面是助理操作员

GroceryItem& GroceryItem::operator=(GroceryItem& copy_item)
{
    if (this == &copy_item)
        return *this;
    else
    {
        delete[] item_name;
        item_name = new char[strlen(copy_item.item_name)+1];
        strcpy(item_name, copy_item.item_name);
        item_price = copy_item.item_price;
        qty_on_hand = copy_item.qty_on_hand;
        qty_purchased = copy_item.qty_purchased;
        return *this ;      // They are the same
    }
}
当我尝试复制到temp2时,从下面的函数调用:

void sort_items(GroceryItem ini_customer_GroceryItem[], int number)
{
    int j = 0, k = 0;
    GroceryItem temp2;

    for (j = 0; j < number - 1; j++)    // n-1 passes
    {
        for (k = number - 1; j < k; k--)    // each pass runs one fewer than the preceding one
        {
            if (ini_customer_GroceryItem[k - 1] > ini_customer_GroceryItem[k])
            {
                temp2 = ini_customer_GroceryItem[k - 1];
                ini_customer_GroceryItem[k - 1] = ini_customer_GroceryItem[k];
                ini_customer_GroceryItem[k] = temp2;
            }
        }
    }
}
void sort_items(杂货店项目ini_customer_杂货店项目[],整数)
{
int j=0,k=0;
食品杂货临时工2;
对于(j=0;jini_customer_GroceryItem[k])
{
temp2=ini_customer_GroceryItem[k-1];
ini_customer_GroceryItem[k-1]=ini_customer_GroceryItem[k];
ini_customer_GroceryItem[k]=temp2;
}
}
}
}
这里是错误

您的
排序项目()
函数应使用该算法,而不是手动复制对象:

/*
temp2 = ini_customer_GroceryItem[k - 1];
ini_customer_GroceryItem[k - 1] = ini_customer_GroceryItem[k];
ini_customer_GroceryItem[k] = temp2;
*/
std::swap(ini_customer_GroceryItem[k - 1], ini_customer_GroceryItem[k]);
无论哪种方式,您都没有实现复制构造函数,只有复制赋值运算符(并且
复制项
在您的实现中应该是
常量
)。看见您需要实现适当的复制构造函数:

GroceryItem::GroceryItem(const GroceryItem& source_item)
{
    item_name = new char[strlen(source_item.item_name)+1];
    strcpy(item_name, source_item.item_name);
    item_price = source_item.item_price;
    qty_on_hand = source_item.qty_on_hand;
    qty_purchased = source_item.qty_purchased;
}
GroceryItem& GroceryItem::operator=(const GroceryItem& copy_item)
{
    if (this != &copy_item)
    {
        GroceryItem temp(copy_item);
        std::swap(temp, *this);
    }
    return *this;
}
然后,您可以使用复制构造函数实现复制赋值运算符:

GroceryItem::GroceryItem(const GroceryItem& source_item)
{
    item_name = new char[strlen(source_item.item_name)+1];
    strcpy(item_name, source_item.item_name);
    item_price = source_item.item_price;
    qty_on_hand = source_item.qty_on_hand;
    qty_purchased = source_item.qty_purchased;
}
GroceryItem& GroceryItem::operator=(const GroceryItem& copy_item)
{
    if (this != &copy_item)
    {
        GroceryItem temp(copy_item);
        std::swap(temp, *this);
    }
    return *this;
}
可简化为:

GroceryItem& GroceryItem::operator=(GroceryItem copy_item)
{
    std::swap(copy_item, *this);
    return *this;
}
当然,如果尚未实现析构函数,请不要忘记析构函数:

GroceryItem::~GroceryItem()
{
    delete[] item_name;
}
当然,还有一个
操作符()
,因为
排序项()
需要一个

现在,说到这里,如果您将
item_name
成员更改为
std::string
而不是
char*
,则根本不需要手动实现析构函数、复制构造函数或复制赋值操作符(只需将默认构造函数设置为零即可初始化数字成员)。编译器为析构函数、复制构造函数和复制赋值运算符生成的默认实现足以为您管理所有数据成员:

class GroceryItem
{
public:
    std::string item_name;
    float item_price;
    int qty_on_hand;
    int qty_purchased;

    GroceryItem();

    bool operator > (const GroceryItem& item) const;
};

GroceryItem::GroceryItem()
{
    item_price = 0.0f;
    qty_on_hand = 0;
    qty_purchased = 0;
};

bool GroceryItem::operator > (const GroceryItem& item) const
{
    return ...;
}

void sort_items(GroceryItem ini_customer_GroceryItem[], int number)
{
    int j = 0, k = 0;
    //GroceryItem temp2;

    for (j = 0; j < number - 1; j++)    // n-1 passes
    {
        for (k = number - 1; j < k; k--)    // each pass runs one fewer than the preceding one
        {
            if (ini_customer_GroceryItem[k - 1] > ini_customer_GroceryItem[k])
            {
                /*
                temp2 = ini_customer_GroceryItem[k - 1];
                ini_customer_GroceryItem[k - 1] = ini_customer_GroceryItem[k];
                ini_customer_GroceryItem[k] = temp2;
                */
                std::swap(ini_customer_GroceryItem[k - 1], ini_customer_GroceryItem[k]);
            }
        }
    }
}
class杂货店项目
{
公众:
std::字符串项目名称;
浮动项目价格;
int现存数量;
国际采购数量;
食品杂货店();
bool操作员>(常量食品杂货项目)常量;
};
GroceryItem::GroceryItem()
{
项目价格=0.0f;
现有数量=0;
采购数量=0;
};
bool GroceryItem::operator>(const GroceryItem&item)const
{
返回。。。;
}
无效排序项目(杂货店项目ini\U客户项目[],国际编号)
{
int j=0,k=0;
//食品杂货临时工2;
对于(j=0;jini_customer_GroceryItem[k])
{
/*
temp2=ini_customer_GroceryItem[k-1];
ini_customer_GroceryItem[k-1]=ini_customer_GroceryItem[k];
ini_customer_GroceryItem[k]=temp2;
*/
标准::交换(ini_customer_GroceryItem[k-1],ini_customer_GroceryItem[k]);
}
}
}
}

你的教授正在教你写StrcPy()和String()过时的C代码,这是有害的,而不是花时间教你真正的C++代码,比如<代码> STD::String < /C>,不需要任何这些废话。为了成为一名熟练的C++开发人员,你没有被教导你需要学习的必要技能。另外,我认为复制构造函数没有问题。内存损坏很可能发生在其他地方。仅仅因为您的代码在一个特定的地方崩溃,即复制构造函数,并不意味着这就是错误所在。请发布一个。这不是复制构造函数,它是赋值运算符,它应该通过常量引用获取其参数。.“下面的函数是复制构造函数”-实际上它是赋值运算符。你的复制构造函数在哪里?很抱歉我没有包括一个。我更新了我的帖子,然后针对你的所有评论,我将更改我的代码,看看它是否有效。发现char的代码有问题,
GroceryItem&GroceryItem::operator=(const GroceryItem©_item){if(this!=©_item){groceryitemp(copy_item);std::swap(temp,*this)}返回*this;}
您看到了什么问题?它在返回此字段的字段中循环。基本上,它在交换和返回之间保持循环。实际上,我最终使用了5个规则来构造带有移动函数等的运算符。虽然随机错误较少,但它们仍然会发生。我没有说明任何东西会在
swap()
内部或之后导致无休止的循环。唯一的循环是
sort\u items()
的内部。