原始对象的C ++指针和复制对象的指针

时间:2011-11-06 13:45:12

标签: c++ pointers

我想澄清一些关于指针的内容,因为我觉得这在C ++中很难实现。当我声明一个指针并将其传递给像:

这样的函数时
//just an example
void showInt(int* numbers)
{
    numbers += 3;
}

int main()
{
    int* a = 10;
    showInt(a);

    return 0;
}

当我将变量a传递给函数时,我实际上是将原始变量传递给它吗?或者它是创建变量的副本,然后将其传递给函数?

如何通知副本或真实/原始副本?

4 个答案:

答案 0 :(得分:3)

你做不到

int* a = 10

没用,编译器会告诉你错误。

执行此操作时:

//just an example
void showInt(int* numbers)
{
    numbers += 3;
}

int main()
{
   int a = 10;
   showInt(&a);

   return 0;
}

您通过了 a 的地址,然后将 3 添加到此地址,因此没有任何更改。

如果你改变:

numbers += 3;

*numbers += 3;

然后你将修改变量 a 的值。

还有一种方法可以做到这一点: 只是改变

void showInt(int* numbers)

void showInt(int& numbers)

那么你可以使用

showInt(a);

并且您将修改 a 的值,并且不会创建副本。

答案 1 :(得分:0)

a指向指针,指向值10。如果要将值10传递给方法,请使用*a。就目前而言,您将内存位置传递给top方法。在该方法中,您将其递增3。

本身没有“复制”和“原始”:在main()中,10存在于内存中,a拥有指向它的指针。在另一个方法[没有名字?]它需要一个int - 而不是一个指针 - 所以如果你修改它你不是改变指针的目标,只是参数(它的作用就像一个局部变量)

希望在某种程度上有所帮助。

[编辑:您现在已更改了使用int*参数而不是int的top方法。这更有意义..让我修改我的答案]

首先我要澄清一下,在你的代码中没有复制任何对象(实际上代码中根本没有真正的对象,只是内存中的int和传递的指针并且可能被修改)。

showInt现在正确地使用指针。它会递增该指针,在这种情况下将其指向未定义/无效的内容。如果你做numbers += 3那么数字只会指向它最初指针的3个字节,这就是所有改变的。这只是在该方法的范围内。

如果您执行了:*numbers += 3,那么您将增加指针的目标,这意味着将10替换为13。无论在何处访问该内存,即main

,这都会生效

我是否可以建议您阅读一下指针vs 引用的好处(例如int&) - 有一篇不错的文章你应该有一个相当不错的'aha'时刻:)< / p>

答案 2 :(得分:0)

使用指针传递指针的副本作为参数,指针指向原始变量。因此,如果取消引用指针,则将具有原始值。记住指针基本上是某个地址,int *是整数的地址,如果改变指针的值,你改变地址,这意味着指针将指向别的东西,如果如果更改指针所指向的值,则会在指向同一对象时更改该值。

void ptrfunc(int *a)
{
  *a = 10;
}

void reffunc(int &a)
{
  a = 50;
}

void valfunc(int a)
{
  a = 30;
}

int main()
{
  int b = 20;
  // Pass the point to b to the function, will alter the original.
  ptrfunc(&b);
  cout << b << endl;
  // Pass a reference to b to the function, will alter the original.
  ptrfunc(b);
  cout << b << endl;
  // Pass the value of b to the function, will not alter the original.
  valfunc(b);
  cout << b << endl;
  return 0;
}

此函数将在第一个cout中打印值10,在下一个cout中打印50,因为在函数中更改了指向和引用的对象的值。 valfunc更改b副本的值,因此不会更改原始值。

答案 3 :(得分:0)

让我们来看看你的例子:

void showInt(int* numbers) // (1)
{
    numbers += 3;          // (2)
}

int main()
{
   int* a = 10;            // (3)   
   showInt(a);             // (4)
   return 0;
}

(1)numbers变量是传递给该函数的变量的副本;

(2)因为(1)此处对numbers所做的所有更改仅保留在此函数内;传递给此函数的原始变量的值将保持不变!但请注意以下内容:您无法更改传递给函数的指针(a)的值,但通过该指针的副本(numbers),您可以更改它指向的值! 这是主要技巧 - 一旦你在函数内部有了地址,就可以在该地址写入,并在函数返回后保留这些更改。在地址写入包括指针解除引用,但幸运的是你没有这样做 - 我说'幸运'因为你传递的地址只是内存中的任意地址(10)。如果你试图在地址10写,你的程序可能会崩溃。

(3)您已将a声明为“指向int的类型”,因此它的值应该是某个int对象的地址。你在这里犯了一个危险的错误,因为你假设10是某个int的有效地址,但你实际上并不知道那个地址是什么。

(4)您将变量a的副本传递给函数。函数将其值存储在numbers变量中并增加它。所以numbers现在包含地址13(不是某个整数变量的地址,其值为13!)。 a虽然保持不变,但仍具有相同的值,10。

你可能想要这样的东西:

void showInt(int* numbers)
{
   *numbers += 3;           // (1)
}

int main()
{
   int a = 10;              // (2)
   showInt(&a);             // (3) 
   return 0;
}

(1)函数修改numbers中保存的地址的值。指针被取消引用。

(2)我们需要有一个int变量的有效地址,而不仅仅是随机选择的地址(如10)。因此我们声明了int变量a。其地址为&a

(3)a的地址通过变量showInt传递给numbers,现在函数可以写入该地址(现在是int对象的有效地址 - {{1}因此修改a的值。当函数返回时,a的值为13.请注意a的地址在此处的任何时间点都不会更改。