调整通过引用传递的动态分配的数组的大小

时间:2013-04-06 19:05:02

标签: c++

我遇到了这个问题:如何在函数内部,通过引用将已经传递的动态分配的数组调整到函数中。 我试过这个,以及这种方法的无数变化。当然这只是一个例子,它应该打印“john”十次,扩展一个通过引用传递的数组,该数组最初只有1(即只有1个名字)。

#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;

int NumLast=-1;


int Surname(string *MyData)
{

          for (int i=0; i<10 ; i++)
          {
            NumLast++;
            string *Temp = new string[NumLast+1];   // temporary array 
            for (int jjj=0; jjj<NumLast; jjj++)
                Temp[jjj]=MyData[jjj];
            delete[] MyData;
            MyData=Temp;
            MyData[NumLast]="John";
          }
          return 0;
}


void main()
{ 
     string *Data = new string[1]; // inizializza l'array 
     Surname(&*Data);
     for (int iii=0; iii<10; iii++)
              cout << Data[iii] << endl; 

     system("pause");
} 

4 个答案:

答案 0 :(得分:1)

你必须通过引用传递。你正在经历价值。你到了

&*Data                                              = Data
The value of the address of what is pointed to Data = Data

然后将值按值传递给Surname。 Surname所做的任何操作都不会影响Data中的main

int Surname(string *MyData)  // This will take a copy of whatever you passed in to MyData

应该是(引用运算符应该在函数定义上。)

int Surname(string*& MyData)
                  ^^

电话会是

void main()
{ 
     string *Data = new string[1];
     Surname(Data);  // The function will take a reference of data.

买我可能会问你为什么要在循环中分配?

答案 1 :(得分:0)

  1. 看起来std :: vector是您案例的最佳解决方案。
  2. 如果您确实需要手动重新分配,请考虑旧学校malloc(),free(),realloc()接口。要记住的主要事情是不要将它与C ++ new / delete接口混合,尽管通常使用malloc()/ free()实现new / delete。
  3. 如果你需要数组,你应该传递不是数组,而是指针(或引用)传递给数组(双指针)。在std :: vector的情况下,足以传递对它的引用。
  4. 使用对std :: vector的引用的另一个参数 - 在指向数组调用者的情况下应该以某种方式通知什么是新的数组大小。

答案 2 :(得分:0)

我决定尝试逐行完成您的代码并指出一些问题并突出显示正在发生的事情。我将从您的main函数开始:

void main()
{ 
    string *Data = new string[1]; // inizializza l'array 
    Surname(&*Data);

    for (int iii=0; iii<10; iii++)
        cout << Data[iii] << endl;
}

好的,所以这段代码的作用就是分配一个字符串,并在名为Data的变量中将指针保存到它。

然后取消引用 Data,因此,返回string,然后获取该字符串地址(即返回与Data)相同。

换句话说,这段代码:

    Surname(&*Data);

与此代码完全相同:

    Surname(Data);

所以,现在让我们来看看Surname

int Surname(string *MyData)
{
    for (int i=0; i<10 ; i++)
    {
        NumLast++;
        string *Temp = new string[NumLast+1];   // temporary array 
        for (int jjj=0; jjj<NumLast; jjj++)
            Temp[jjj]=MyData[jjj];
        delete[] MyData;
        MyData=Temp;
        MyData[NumLast]="John";
    }
    return 0;
}

这个奇怪的函数接受一个指向字符串的指针并循环10次做东西。让我们看看循环的第一次迭代会发生什么......

首先,它会增加NumLast(从-1增加到0)。然后它分配一个长度为NumLast + 1的字符串数组(即长度为1)。到目前为止一切都很好。

现在您可能认为该函数将进入for循环。但它不会:请记住,此时NumLastjjj都是0,因此jjj < NumLast为假。

然后代码将delete[] MyData(也就是说,它将删除任何MyData个点),将MyData设置为指向循环中先前分配的临时数组,然后设置第一个元素(在索引0处)到字符串"John"

在循环的第二次迭代中,函数再次递增NumLast(现在为1)。它将再次分配一个字符串数组,这个时间长度为2

这次将输入循环。它会将MyData中的第一个条目复制到Temp的第一个条目中。它会退出。

同样,MyData将被删除,指针将指向新分配的数组。

冲洗。泡沫。重复。

最后,该函数将退出。我们回到main,现在将执行这段代码:

for (int iii=0; iii<10; iii++)
    cout << Data[iii] << endl;

等一下。 Data指向哪里?嗯......它指的是很久以前就已被删除的数据。为什么呢?

好吧,Surname收到了Data指针的副本。当它调用delete[] MyData时,它删除了它MyData指向的数组(与Data指向的数组相同)。当Surname稍后MyData=Temp时,所有更改的内容都是MyData(指针的副本本地到函数Surname)和{{1} (Data中的指针)未受影响,并继续指向现在已删除的内存。

其他人已经解释了如何获得你想要的效果,我不会重复他们所写的内容。但我会敦促你坐下来思考main做了什么以及代码如何不清楚和令人困惑,以及如何重写它以便它更容易理解,更不容易出错。

答案 3 :(得分:0)

对于那些将来需要解决相同问题的人来说,修改后的代码是:

#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;

int NumLast=-1;
int Surname(string *&MyData)
{       
     for (int i=0; i<10 ; i++)
     {
           NumLast++;
           string *Temp = new string[NumLast+1];   
           for (int jjj=0; jjj<NumLast; jjj++)
                Temp[jjj]=MyData[jjj];
           delete[] MyData;
           MyData=Temp;
           MyData[NumLast]="franci";
      }
      return 0;
}


void main()
{ 
      string *Data = new string[1]; // inizializza l'array 
      Surname(Data);  
      for (int iii=0; iii<10; iii++)
           cout << Data[iii] << endl;    
      system("pause");
}