0

我陷入了这个问题:如何在函数内部调整已通过引用传递给函数的动态分配数组的大小。我尝试了这个,以及这种方法的无数变化。当然这只是一个例子,它应该打印“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

4 回答 4

1

您必须通过引用传递。你是按价值传递的。你得到

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

然后将其按值传递给姓氏。对它做的任何事情Surname都不会影响Datain 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.

购买 请问为什么要循环分配?

于 2013-04-06T19:07:18.933 回答
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,因此,取回 astring然后获得该字符串的地址(即取回与 相同的东西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(从-10)。然后它分配一个字符串数组,长度为NumLast + 1(即长度1)。到目前为止,一切都很好。

现在你可能认为函数会进入for循环。但它不会:记住,在那一点上NumLastjjj两者都是0,因此,jjj < NumLast是错误的。

然后代码将delete[] MyData(即,它将删除任何MyData指向),设置MyData为指向在循环中较早分配的临时数组,然后将第一个元素(在 index 处0)设置为 string "John"

在循环的第二次迭代中,函数再次递增NumLast(现在为 1)。它将再次分配一个字符串数组,这次是 length 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指针的副本)和(函数中的指针)不受影响并继续指向现在删除的内存。SurnameDatamain

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

于 2013-04-06T19:33:42.987 回答
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");
} 
于 2013-04-08T19:51:23.947 回答
0
  1. 看起来 std::vector 是您案例的最佳解决方案。
  2. 如果你真的需要手动重新分配,想想老派的 malloc()、free()、realloc() 接口。要记住的主要事情是不要将它与 C++ new/delete 接口混合,尽管通常 new/delete 是使用 malloc()/free() 实现的。
  3. 如果您需要数组,则不应将数组而是指针(或引用)传递给数组(双指针)。在 std::vector 的情况下,传递对它的引用就足够了。
  4. 使用对 std::vector 的引用的另一个参数 - 在指向数组调用者的指针的情况下,应该以某种方式通知什么是新数组大小。
于 2013-04-06T19:11:00.510 回答