通过复制到函数将指针传递给动态分配的数组会产生意外结果

Passing pointer to dynamically allocated array by copy to function has unexpected result

我只是忙于将指针传递给函数以了解它是如何工作的,我遇到了一些意想不到的行为。我有以下代码:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <iomanip>

using namespace std;

struct t
{
    string x;
    string y;
};

void foo(t*);

int main()
{

    t* ts = new t[2];
    ts[0].x = "t1.x";
    ts[0].y = "t1.y";
    ts[1].x = "t2.x";
    ts[1].y = "t2.y";

    foo(ts); 

    cout << ts[0].x << endl;

}

void foo(t* s)
{
    delete[] s;
    s = new t[2];
    s[0].x = "FOO.X";
    s[1].y = "FOO.Y";
}

有趣的是,此处的输出是 "FOO.X"。我预计,由于 foo 内部,s 是指针 ts 的副本,当我 delete[] s 我有效地 delete[] ts 因为它们都指向相同地址。那么s = new t[2];应该对ts没有影响。在 foo returns 之后,我不应该再访问 s 或它指向的数组,ts 应该指向谁知道在哪里。我错过了什么吗?

注意:这只是我做的一个测试项目,我不断地编写和擦除代码块来测试不同的概念。所有 includes 和 using namespace std 都是为了便于使用,它不是我为任何实际用途而编写的代码,纯粹是教育性的。另外,我使用的是 MS VS 2013。

尝试像这样更改您的 foo() 并查看结果:

void foo(t* s)
{
  delete[] s;

  // Additional memory allocation
  t* u = new t[2];

  s = new t[2];
  s[0].x = "FOO.X";
  s[1].y = "FOO.Y";
}

通过添加另一个内存分配,我将 s 移动到内存中的另一个位置,不再与 ts 重叠。否则,s 只是简单地分配在 ts 之前所在的同一位置。

正如评论中所指出的,您正在观察 未定义的行为,您绝不应该依赖它。上面的例子很好地说明了这一点。