【发布时间】:2021-06-04 10:28:50
【问题描述】:
我一直在从事一个使用大量双指针的项目,但我发现我遇到了一些错误。在花了一些时间研究它之后,我意识到问题是当你通过一个指向 const 对象的指针的引用传递一个非常量对象时,它最终会通过副本而不是引用传递。我不明白为什么会这样,因为引用只是一个别名,如果您尝试更改该范围内的对象的某些内容,则 const 部分应该只会导致错误。为了进一步混淆,当传递 const 对象的双指针或它只是对 const 对象的引用时,不会发生这种情况。谁能解释为什么会发生这种情况以及这个特殊案例与我所包含的其他案例有何不同?
#include <iostream>
void PassByConstPtrRef(int const *const &num_ptr_ref)
{
std::cout << &num_ptr_ref << std::endl;
}
void PassByPtrRef(int *const &num_ptr_ref)
{
std::cout << &num_ptr_ref << std::endl;
}
void PassByPtrPtr(int const *const *const num_ptr_ref)
{
std::cout << num_ptr_ref << std::endl;
}
void PassByConstRef(int const &num)
{
std::cout << &num << std::endl;
}
int main()
{
int *num_ptr = new int{ 10 };
int *const *num_ptr_ptr = &num_ptr;
int *const &num_ptr_ref = *num_ptr_ptr;
std::cout << num_ptr_ptr << " : " << &num_ptr_ref << std::endl; // is equal
std::cout << num_ptr_ptr << " : ";
PassByConstPtrRef(num_ptr_ref); // is not equal
std::cout << num_ptr_ptr << " : ";
PassByPtrRef(num_ptr_ref); // is equal
std::cout << num_ptr_ptr << " : ";
PassByPtrPtr(&num_ptr_ref); // is equal
int foo = 4;
int &bar = foo;
std::cout << &foo << " : ";
PassByConstRef(bar); // is equal
}
输出:
0x7ffeeb6d59c8 : 0x7ffeeb6d59c8
0x7ffeeb6d59c8 : 0x7ffeeb6d59b0
0x7ffeeb6d59c8 : 0x7ffeeb6d59c8
0x7ffeeb6d59c8 : 0x7ffeeb6d59c8
0x7ffeeb6d59ac : 0x7ffeeb6d59ac
【问题讨论】:
-
@churill 谢谢,我已经在底部添加了输出。
-
@JaMiT 我很高兴收到对我的猜测的更正,如果你有的话?它可能会让我不那么困惑。在我来这里提问之前,我只是想自己弄清楚,所以我想我应该分享一下我在哪里。
-
@JaMiT 不会让我的代码适用于 int 但不适用于类吗?它似乎在这两种情况下都不起作用,我通过删除 const 让我的原始代码正常工作。
-
啊...我看到了混淆的一个原因。结果在 gcc 9 和 gcc 10 之间以及 clang 9 和 clang 10 之间发生了变化。在 10+ 版本中进行测试的人不会看到差异。
-
@JaMiT 是的,这正是我的问题。 MSVC 也在产生 OPs 结果。这是一个test on godbolt 供参考,显示了不同版本的2 个编译器。
标签: c++ pointers reference constants double-pointer