调整动态分配的指针数组的大小(复制构造函数不起作用?)

Posted

技术标签:

【中文标题】调整动态分配的指针数组的大小(复制构造函数不起作用?)【英文标题】:Resizing a dynamically allocated array of pointers (Copy Constructor not working?) 【发布时间】:2017-10-04 21:05:06 【问题描述】:

在我提出问题之前,让我先介绍一下我的程序存在的限制: - 不允许使用向量(这是为了分配)

我正在测试我的课程,以确保他们按照我的预期去做。我正在尝试增加动态分配的指针数组的大小。在调试时,我发现当我将 pTemp[i] 设置为 pTransactions[i] 时,复制构造函数没有被使用;当 pTransactions[i] 在几行之后被删除时,应该在 pTemp[i] 中的数据就消失了(参见下面的代码)。我有什么明显的遗漏吗?

以下是与我的问题相关的文件:(如果您需要更多代码,请告诉我)

另外,对我的代码中缺少颜色表示歉意。这是我的第一篇文章,我并不完全习惯这里的格式。编辑:开个玩笑,我现在看到它只是在稍后添加颜色......

(来自 Account 类的部分代码——pTransactions 是动态分配的指针数组)

void Account::createNewTransaction(Transaction* newTrans) 
if (numberOfTransactions > 0) 
    //Create temp pointer
    Transaction **pTemp = new Transaction*[++numberOfTransactions];

    //Copy array to temp
    if (*pTransactions) 
        for (int i = 0; i < numberOfTransactions - 1; i++) 
            Transaction *tempTrans = pTransactions[i];
            pTemp[i] = tempTrans;
        

        for (int i = 0; i < numberOfTransactions - 1; i++) 
            delete pTransactions[i];
        
        delete[] pTransactions;
    

    //Recreate array
    pTransactions = new Transaction*[numberOfTransactions];


    for (int i = 0; i < numberOfTransactions; i++) 
        pTransactions[i] = pTemp[i];
    

else 
    numberOfTransactions++;
    pTransactions = new Transaction*[numberOfTransactions];

pTransactions[numberOfTransactions - 1] = newTrans;

double oldBalance = balance;    //Variable to hold original balance

//Complete correct type of transaction
if (newTrans == dynamic_cast<Deposit*>(newTrans))
    balance = static_cast<Deposit*>(newTrans)->makeDeposit(balance);
else if (newTrans == dynamic_cast<Withdraw*>(newTrans))
    balance = static_cast<Withdraw*>(newTrans)->makeWithdrawal(balance);
else
    balance = static_cast<Check*>(newTrans)->makeCheck(balance);

//If balance equals oldBalance -- no transaction actually occurred
if (balance == oldBalance) 
    numberOfTransactions--;

Transaction.ccp -- Transaction 是一个抽象类

#include "Transaction.h"

Transaction::Transaction()

    id = ++transactionTracker;


Transaction::~Transaction()



int Transaction::getTransactionTracker()

    return transactionTracker;


//Mutator Functions
void Transaction::setId(int newId) 
    id = newId;


void Transaction::setAmount(double amt) 
    amount = amt;


//Other Functions
void Transaction::cancelTransaction() 
    transactionTracker--;

Deposit.cpp -- Deposit 是 Transaction 的派生类

#include "Deposit.h"
#include <iostream>

//Constructor
Deposit::Deposit(double amt)

    setAmount(amt);


//Copy Constructor
Deposit::Deposit(const Deposit &obj)

    id = obj.id;
    amount = obj.amount;


//Deconstructor
Deposit::~Deposit()



//Functions
double Deposit::makeDeposit(double balance) 
    return balance + amount;


//Overloaded function (from Transaction)
void Deposit::toString() 
    cout << "-------------------------------------\n";
    cout << "Transaction #" << id << endl;
    cout << "Deposited $" << amount << endl;
    cout << "-------------------------------------\n";


//Overloaded = operator
const Deposit Deposit::operator=(const Deposit &obj)

    id = obj.id;
    amount = obj.amount;
    return *this;

Withdraw.cpp -- Withdraw 是 Transactions 的派生类

#include "Withdraw.h"
#include<iostream>

//Constructor
Withdraw::Withdraw(double amt)

    setAmount(amt);


//Copy Constructor
Withdraw::Withdraw(const Withdraw &obj)

    id = obj.id;
    amount = obj.amount;


//Destructor
Withdraw::~Withdraw()



//Functions
double Withdraw::makeWithdrawal(double balance) 
    if (balance > amount) 
        return balance - amount;
    
    else 
        cancelTransaction();
        cout << "Amount exceeds balance.  Request denied.\n";
        return balance;
    


Overloaded function (from Transaction)
void Withdraw::toString() 
    cout << "-------------------------------------\n";
    cout << "Transaction #" << id << endl;
    cout << "Withdrew $" << amount << endl;
    cout << "-------------------------------------\n";


//Overloaded = operator
const Withdraw Withdraw::operator=(const Withdraw &obj)

    id = obj.id;
    amount = obj.id;
    return *this;

Checks.cpp -- Checks 是 Transactions 的派生类

#include "Check.h"
#include<iostream>

//Constructor
Check::Check(double amt, string name)

    setAmount(amt);
    setName(name);
    checkNumber = ++numberedChecks;


//Copy Constructor
Check::Check(const Check &obj)

    id = obj.id;
    amount = obj.amount;
    checkNumber = obj.checkNumber;
    name = obj.name;


//Deconstructor
heck::~Check()



//Mutator Function
void Check::setCheckNumber(int number) 
    checkNumber = number;


void Check::setName(string newName) 
    name = newName;


//Other Functions
double Check::makeCheck(double balance)

    if (balance > amount)
        return balance - amount;
    else 
        cancelTransaction();
        cout << "If that check were to go through, you would have an overdraft.  Request denied.\n";
        return balance;
    


//Overloaded Function (from Transaction)
void Check::toString() 
    cout << "-------------------------------------\n";
    cout << "Transition #" << id << endl;
    cout << "Check #" << checkNumber << endl;
    cout << "For the amount of $" << amount << endl;
    cout << "Made out to " << name << endl << endl;
    cout << "-------------------------------------\n";


//Overloaded = operator
const Check Check::operator= (const Check &obj)

    id = obj.id;
    amount = obj.amount;
    checkNumber = obj.checkNumber;
    name = obj.name;
    return *this;

【问题讨论】:

那么问题是什么,没有调用复制构造函数或其他什么? 不相关:Transaction **pTemp = new Transaction*[++numberOfTransactions]; 在每次添加时强制调整大小。考虑将大小增加一倍以上以减少调整大小的次数。 不相关:代码中有很多谷壳。例如:Transaction *tempTrans = pTransactions[i]; pTemp[i] = tempTrans; 可能是 pTemp[i] = pTransactions[i]; 最令人震惊的是 pTransactions = new Transaction*[numberOfTransactions]; for (int i = 0; i &lt; numberOfTransactions; i++) pTransactions[i] = pTemp[i]; 应该可能只是 pTransactions = pTemp; 或非常相似的东西。 我假设没有调用复制构造函数,但我不确定为什么。 pTemp[i] 只是复制地址而不是内容。 pTempTransaction **pTemp[i]Transaction *。如果要复制内容,则需要取消引用所有指针:*pTemp[i] 【参考方案1】:

考虑这段代码:

Something *a = new Something;
Something *b = a;
delete a;

在此代码行 2 中,Something 的复制构造函数不会被调用,您只需将一个指针分配给另一个指针,您不会复制对象。当你销毁a 指向的对象时,你不能再使用b,因为它与a 是同一个指针,即它指向同一个内存。您的代码中有这个确切的问题:

if (*pTransactions) 
    for (int i = 0; i < numberOfTransactions - 1; i++) 
        Transaction *tempTrans = pTransactions[i];
        pTemp[i] = tempTrans;
    

    for (int i = 0; i < numberOfTransactions - 1; i++) 
        delete pTransactions[i];
    
    delete[] pTransactions;

目前还不清楚为什么您希望调用 copy ctor,更重要的是为什么需要调用它,只是不要破坏对象,只破坏存储指针的内存。

这不是错误,但是创建临时数组,将所有内容复制到那里然后再次复制到新数组中是非常无效的。而且将数组大小增加一也不是一个好主意。

什么是更好的方法?

只需将当前指针移动到 temp,然后分配新指针并复制指针。请记住,将一个指针复制到另一个是简单的操作(例如将一个 int 分配给另一个),但复制数组不是:

Transaction **pTemp = pTRansactions;
pTransactions = new Transaction*[capacity];
if( pTemp )  
   // copy existing transactions from pTemp to pTransactions
   delete[] pTemp;

// done

并且您应该有另一个成员capacity 并在大小达到它时将其增加 delta 并在这种情况下执行此代码。您可能希望制定一些减少容量的策略,但可以省略。

【讨论】:

有什么更好的方法? 顺便说一句,谢谢。我想我对它是指针而不是对象感到困惑。我找到了一种让代码工作的方法。您对我实际所做的事情的简化对我帮助最大……所以谢谢。

以上是关于调整动态分配的指针数组的大小(复制构造函数不起作用?)的主要内容,如果未能解决你的问题,请参考以下文章

指针数组的动态内存分配

附加函数在调整大小的数组中不起作用

如何从函数返回动态分配的指针数组?

调整c++数组的大小和复制

拷贝构造函数 和 赋值操作符重载

子节点的 JavaFX GridPane 动态调整大小以填充分配的区域