【问题标题】:Why does passing a pointer by reference after passing it by value point to the original memory location?为什么按值传递指针后按引用传递指针指向原始内存位置?
【发布时间】:2015-05-26 18:41:01
【问题描述】:

我正在与 SWIG 合作,在 Python 中封装一些 C++ 代码。我包装的 C++ 函数定义为:

template <typename T>
void getData(const std::string& fileName, T*& data);

数据作为对指针的引用传递,因为文件中的数据可以与指针具有相同类型或不同类型。在前一种情况下,我们只需将指针替换为指向文件数据的指针,在后一种情况下,我们使用 std::copy 将每个值转换为请求的类型。

现在我们来回答我的问题,SWIG 包装为我提供了以下功能:

void wrap_getData(const std::string& fileName, T* data) {
     getData(fileName, data);
}

这被称为使用:

unsigned char* data = new unsigned char[dataSizeInFile]
wrap_getData(fileName, data)

由于文件中的数据类型也是无符号字符,通常它只会更改指针内存地址(如果我使用的是 getData)。但是,现在我希望这不会发生,但确实发生了。

例如,指针的原始内存地址 (&ptr) = 0x000000000c840070,然后在 wrap_getData 函数内部,数据指针内存地址 (&ptr) 为 0x00000000002393e8,正如预期的不同,因为指针被复制。但是现在,当我通过引用实际的 getData 函数来传递这个指针时,内存地址 (&ptr) 再次是 0x000000000c840070,这是我没想到的,我希望它保持 0x00000000002393e8,因为副本是通过引用传递的。为什么会这样?

【问题讨论】:

  • 请编辑您的问题,以便在任何特定点更清楚地定义“地址”的含义。使用诸如“指针的地址”之类的术语来表示&amp;ptr,使用“指针指向的地址”来简单地表示ptr。现在真的不清楚你的意思是什么时候,这两个值中的哪一个不是你所期望的。
  • 请到这里编辑您看到的内容以匹配您要解释的内容:coliru.stacked-crooked.com/a/61d21d0af7c9b1e2
  • PaulMcKenzie,我编辑了它,Coliru Viewer 中的行为确实是我所期望的 (coliru.stacked-crooked.com/a/5080224fe682ebe0),但不是我在 Visual Studio 2012 中看到的行为。所以,我不确定为什么它在那里表现得像预期的那样,而不是在我的系统上。
  • @Geert - 好吧,我有 VS 2008 和 VS 2013,行为与 Coliru 示例相同。
  • @PaulMcKenzie,你是对的,我应该看起来更好。我想出了自己的问题,这是因为运气。我在 Coliru 中做了一个最小的例子来展示这一点 (coliru.stacked-crooked.com/a/9f09393b04b51926)。当在 getData 函数中删除数组并立即在使用相同内存位置的数组中创建一个相同大小的新结果时(尝试将 50 更改为 5)。如果我制作一个更大的数组,它不再使用相同的内存位置,事情就会分崩离析。所以正如预期的那样,它不应该工作。感谢您的帮助!

标签: c++ pointers pass-by-reference pass-by-value


【解决方案1】:

你传入了指针。在函数中,创建了一个新指针,但显示给同一个对象。并且通过指针,可以在函数中更改该对象(指针指向的对象)。在函数之后,用函数创建的指针被销毁/释放。原始指针的内存位置始终保持不变,与指针指向的值相同。

这就是我的想法。我可能读得太快了。

在调用getData(fileName, data); 之前,指针data 位于地址“a_17”上,其值例如为“v_22”,在调用函数时,函数参数T*&amp; data 被创建并获得与论据data。所以它得到一个新地址(例如“a_34”),它的值是“v_22”。

如果你想用函数改变指针指向的位置,只需传入一个指向指针的指针。

编辑:添加绘图: link 这就是我的看法。我承认我对函数参数中的这个“*&”不熟悉,我更喜欢使用指针和指向指针的指针。

【讨论】:

  • 不完全确定您的意思。当我第一次传递指针(mem.address a_17)时,会生成一个副本(mem.address a_18)。当我通过引用传递此副本时,我希望此引用显示 a_18,而不是 a_17,对吗?
  • 拥有例如char* data 然后调用{{ f_data(data); where function is void f_data(char*&amp; in_data) }} 与相同的char* data 相同,您将调用{{ f_data(&amp;data); 这是无效@987654331 @ 但是你必须在函数中使用 *in_data 。 }} 函数参数“char*& in_data”表示对指向 char 的指针的引用。这意味着如果我们改变 in_data,我们就会改变数据。
  • 嗨 iNyuu,对不起,我想我们不在同一个页面上。请参阅我对 Paul McKenzie 评论的回复,其中包含我所期望的代码。
【解决方案2】:

这是偶然的。如果您删除一个数组,然后立即创建一个大小完全相同的新数组,则很有可能它将使用相同的内存地址。其他行为正常。

【讨论】:

    猜你喜欢
    • 2014-04-07
    • 2016-12-25
    • 2014-09-08
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多