动态分配内存,复制构造函数中的错误

时间:2016-05-14 01:12:02

标签: c++ memory constructor copy

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

默认构造函数

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;
}
;

下面是assigment opperator

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;
            }
        }
    }
}

这是错误

image

1 个答案:

答案 0 :(得分:1)

您的sort_items()函数应使用std::swap()算法,而不是手动复制对象:

/*
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]);

无论哪种方式,您都没有实施复制构造函数,只有复制赋值运算符(并且copy_item在您的实现中应为const )。见Rule of Three。您需要实现正确的复制构造函数:

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;
}

当然,operator>()需要sort_items()

现在,尽管如此,如果您将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]);
            }
        }
    }
}