【发布时间】:2026-02-17 20:15:02
【问题描述】:
例如:void foo( int& i ); 是不允许的。这是有原因的,还是不是规范的一部分?据我了解,引用通常以指针的形式实现。在 C++ 中,void foo( int* i ) 和 void foo( int& i ) 之间是否存在任何功能差异(不是语法/语义)?
【问题讨论】:
例如:void foo( int& i ); 是不允许的。这是有原因的,还是不是规范的一部分?据我了解,引用通常以指针的形式实现。在 C++ 中,void foo( int* i ) 和 void foo( int& i ) 之间是否存在任何功能差异(不是语法/语义)?
【问题讨论】:
因为引用是 C++ 特性。
【讨论】:
void * 到任何指针的转换。在 C++ 中,对这些类型转换的需求很少,无论如何很少会发生错误,当它发生时,我希望用static_cast 纠正它们。这些演员表并不是没有用的,因为它们标志着你的程序中的一个弱点。这都是关于强类型安全的。
Ownership Symantics 的概念。这是动态分配的对象具有明确所有者的地方。然后所有者清理所有内存并删除所有那些作为 C 代码(初级 C 代码)标志的令人讨厌的内存泄漏。指针不适用于Ownership Symantics,因为没有迹象表明谁拥有指针,它只是一个指针。
引用只是指针的语法醋。它们的实现是相同的,但是它们隐藏了被调用函数可能会修改变量的事实。它们真正发挥重要作用的唯一一次是使其他 C++ 特性成为可能——想到了运算符重载——根据你的观点,这些也可能是句法醋。
【讨论】:
const 引用是可以的,因为它就像按值传递,只是效率更高,但允许 swap(a, b) 而不是 swap(&a, &b) 绝对是一个错误功能。 C# 的 ref 和 out 关键字做到了这一点。
foo 必须检查它是否被称为foo((int *)0),而它也不能检查它是否未被称为foo((int *)1) 或任何其他数十亿个可能的无效指针值?除非函数的文档明确声明它接受某些无效指针值并赋予它们特殊含义,否则编写代码以空指针参数调用此类函数的白痴是一个责任 用于调用 UB。
例如:void foo(int& i);不允许。这是有原因的,还是不是规范的一部分?
这不是规范的一部分。引用的语法“type&”是在 C++ 中引入的。
据我了解,引用通常以指针的形式实现。在 C++ 中,void foo( int* i ) 和 void foo( int& i ) 之间是否存在任何功能差异(不是语法/语义)?
我不确定它是否属于语义差异,但引用可以更好地防止取消引用空值。
【讨论】:
因为& 运算符在 C 中只有 2 个含义:
其操作数的地址(一元),
和,按位与运算符(二进制)。
int &i; 不是 C 中的有效声明。
【讨论】:
int &i; 在 C++ 中也不是有效的“声明”!
对于函数参数,指针和引用之间的区别并没有那么大,但在许多情况下(例如成员变量),引用大大限制了你可以做的事情,因为它不能被反弹。
【讨论】:
C 中不存在引用。但是,C 确实具有通过引用传递的可变参数。示例:
int foo(int in, int *out) { return (*out)++ + in; }
// ...
诠释 x = 1;整数 y = 2;
x = foo(x, &y);
// x == y == 3.
然而,在更复杂的 foo()s 中,忘记在每次使用中取消引用“out”是一个常见的错误。 C++ 引用允许更平滑的语法来表示闭包的可变成员。在这两种语言中,这可能会因为多个符号引用相同的存储而混淆编译器优化。 (考虑“foo(x,x)”。现在不确定“++”是仅出现在“*out”之后还是出现在“in”之后,因为两次使用之间没有序列点,增量只需要在取左表达式的值之后的某个时间发生。)
此外,显式引用消除了 C++ 编译器的两种情况。传递给 C 函数的指针可以是可变参数或指向数组的指针(或许多其他东西,但这两个充分说明了歧义)。对比“char *x”和“char *y”。 (...或未能如预期那样这样做。)通过引用传递给 C++ 函数的变量无疑是闭包的可变成员。例如,如果我们有
// 在类 baz 的范围内
私人:int bar(int &x, int &y) {return x - y};
公共 : int foo(int &x, int &y) {return x + bar(x,y);}
// 退出作用域并继续徘徊...
整数a = 1;诠释 b = 2;巴兹 c;
a = c.foo(a,b);
我们知道几件事:
bar() 只能从 foo() 调用。这意味着 bar() 可以被编译,以便在 foo() 的堆栈框架中找到它的两个参数,而不是它自己的。这被称为复制省略,这是一件很棒的事情。
当函数的形式为“T &foo(T &)”时,复制省略变得更加令人兴奋,编译器知道有一个临时的进出,编译器可以推断出结果可以就地构造的论点。然后不需要复制临时输入或结果输出。可以编译 foo() 以从某个封闭堆栈帧中获取其参数,并将其结果直接写入某个封闭堆栈帧。
最近一篇关于复制省略的文章和(惊喜)如果您在现代编译器中传递 按值 效果会更好(以及 C++0x 中的右值引用如何帮助编译器跳过更无意义的副本),请参阅http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/。
【讨论】: