【问题标题】:How come the return value of the static, non-local returned pointer is always zero?为什么静态的、非本地返回的指针的返回值总是为零?
【发布时间】:2014-02-11 23:08:09
【问题描述】:
#include <iostream>
using namespace std;
int take(int &takevalue, int &doubletake, int *pointer);
int main()
{
 int chaka;
 int sheppa;
 int *lostlove;
 take(chaka, sheppa, lostlove);
 cout << lostlove;
}
int take(int &takevalue, int &doubletake, int *pointer)
{
 pointer = &takevalue;
 return *pointer;
}

上面的代码可以正常工作,但是指针的值为0。所以,我尝试在非本地进行,其中表示的数据将来自堆并在程序结束时自动删除:

#include <iostream>
using namespace std;
static int *pointer = 0;
int take(int &takevalue, int &doubletake, int *pointers);
int main()
{
int chaka;
int sheppa;
take(chaka, sheppa, pointer);
cout << pointer;
}
int take(int &takevalue, int &doubletake, int *pointers)
{
pointer = &takevalue;
return *pointer;
}

但是,“指针”的值仍然是 0,即使在分配了 takevalue 的地址之后。使用调用堆栈时,takevalue不应该有地址吗?为什么指针总是0?

【问题讨论】:

  • 您的代码无法编译(pointerspointer)。您应该复制您的实际代码。 BTW,答案是指针是按值传递的。
  • @EdS。问题中的两个代码示例都可以编译。有一个参数pointers,但这并不意味着全局变量pointer停止存在。
  • @EdS。 Pointers 是参数,但是静态传递的 int 是指针。区别没有任何意义。都为我编译。参数名称在调用时不需要匹配参数。
  • @hvd:我什至没有看到那个声明,我的错。
  • @AndyHarglesis:我指的不是这个。我指出了take 中使用的pointer,但没有看到它是静态声明的。

标签: c++ pointers static heap-memory callstack


【解决方案1】:

您希望从 take 的参数中更改指针的值,但这不会发生,因为 int* 指针将是您的函数的本地指针。如果要更改指针的值,则需要创建一个双指针(或 ref 指针)。示例:

take(int& value, int** pointer) {
    *pointer = &value;
}

这将改变你的指针指向的地址。

【讨论】:

  • 双倍指针如何做到这一点?它不会仍然是堆栈上的函数的本地吗?
  • int** 将是本地的(意味着您将无法在函数外部更改 int**),但您可以更改 int** 指向的内容(即指针值,int* )。尝试更多地研究函数参数和指针(尤其是指针)。指针只是指向内存地址的 32 位(或 64 位)地址。这些 32 位将是您的功能的本地。这就是为什么 int** 在这里会有所帮助的原因。
  • 但它是静态的,那么与将它作为参数传递并使用局部变量直接在现场分配它有什么区别?
  • 因为你在全局范围内声明它,在你的 main 之外,这意味着它可以在任何地方访问。
  • @Syl 但这并不能完全回答我的问题
【解决方案2】:

运行我得到的最后一个程序

[H:\开发\测试] > 一个 0x23fe4c [H:\开发\测试] > _

问题解决了。

【讨论】:

  • 第一个呢?有什么见解吗?
  • @Andy:第一个与您期望的不同呢?请注意,第一个程序可以做任何事情,因为它使用并输出一个indeterminate(未初始化的)指针值,即Undefined Behavior。 UB 包括导致红鼻守护程序出现的程序。
【解决方案3】:

在这个函数声明中

int take(int &takevalue, int &doubletake, int *pointer);

如果不是引用,每个参数都是函数的局部变量。所以在函数中对这样的参数所做的任何更改都会在退出函数后被丢弃,并且不会影响原始参数。

您应该像前两个参数一样将第一个参数声明为引用

int take(int &takevalue, int &doubletake, int * &pointer);

至于第二个函数定义

int take(int &takevalue, int &doubletake, int *pointers)
{
pointer = &takevalue;
return *pointer;
}

那么它的第三个参数根本就没有被使用。所以你可以将函数重写为

int take(int &takevalue, int &doubletake)
{
pointer = &takevalue;
return *pointer;
}

虽然第二个参数也没有使用。:)

所以函数可以更简单

int take(int &takevalue)
{
pointer = &takevalue;
return *pointer;
}

【讨论】:

  • 那么从分配在所有函数之外的堆内存中静态使用它并传递它也是静态的有什么区别?
  • @Andy Harglesis 与其他参考文献相同。也就是说,它是对原始参数的引用,因此任何更改都将使用原始参数完成。也就是说,如果您更改指针的值,实际上您将更改原始指针。
  • 再看一遍,我修改了。
  • 那么从分配在所有函数之外的堆内存中静态使用它并传递它也是静态的有什么区别?本质上,如果我可以使用它而不必将它作为参数传递(因为它是全局的),那么以这种方式传递它而不是仅仅分配它会有什么区别?
  • @Andy Harglesis 你修改了什么?因为我已经写了第二个函数定义中的第三个参数,所以没有使用。在函数体中,您直接使用全局指针。
【解决方案4】:

当您考虑指针实际上是什么 - 一个整数,其值为内存地址 - 事情就会开始变得更加清晰。

让我们看看你原来的声明:

int take(int &takevalue, int &doubletake, int *pointer);

可以这样想:

int take(int &takevalue, int &doubletake, int address);

所以当你声明这个时:

int *lostlove;

你真的是这样声明的:

int address_of_an_int;

因此,当你调用它时:

take(chaka, sheppa, lostlove);

您正在将lostlove 的值按值 传递给take()

现在,让我们看看take() 做了什么:

int take(int &takevalue, int &doubletake, int *pointer)
{
    pointer = &takevalue;
    return *pointer;
}

换个思路,其实是这样的:

int take(int &takevalue, int &doubletake, int address)
{
    address = (int) &takevalue;
    return value_that_is_located_at_address;
}

因此,正如您所见,最后一个参数是按值传递,因此您正在修改仅存在于函数中的局部变量。由于参数不是通过引用(与其他参数一样)或通过指针传递,因此无法使用新值修改调用者的变量 (lostlove)。这就是为什么你看不到它改变的原因。

因此,考虑到这一点,要使您的原始代码按您期望的方式工作,您需要改为这样做:

int take(int &takevalue, int &doubletake, int* &pointer);

int main()
{
    int chaka;
    int sheppa;
    int *lostlove;
    take(chaka, sheppa, lostlove);
    cout << lostlove;
}

int take(int &takevalue, int &doubletake, int* &pointer)
{
    pointer = &takevalue;
    return *pointer;
}

或者这个:

int take(int &takevalue, int &doubletake, int **pointer);

int main()
{
    int chaka;
    int sheppa;
    int *lostlove;
    take(chaka, sheppa, &lostlove);
    cout << lostlove;
}

int take(int &takevalue, int &doubletake, int **pointer)
{
    *pointer = &takevalue;
    return **pointer;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2020-07-30
    相关资源
    最近更新 更多