C++ c++;将单个变量作为引用和常量引用传递
让我们假设有一个函数C++ c++;将单个变量作为引用和常量引用传递,c++,C++,让我们假设有一个函数f,它接收两个变量,一个是引用变量,另一个是常量引用变量 如果我将单个变量作为两个参数传递,则会发生错误: 结果: a: 6 b: 6 代码 void f(内部和a、内部和b) { a=a+1; std::cout这似乎“正常”工作 您已将函数定义为接受两个参数。声明第一个参数是为了指示引用的整数a可以在f()中更改,但b不应更改 这两个参数都是通过引用传递的,您违反了const的使用,因为更改的a也被引用为b 这种行为是我在没有优化的情况下所期望的。(实际存储为m的整数值
f
,它接收两个变量,一个是引用变量,另一个是常量引用变量
如果我将单个变量作为两个参数传递,则会发生错误:
结果:
a: 6
b: 6
代码
void f(内部和a、内部和b)
{
a=a+1;
std::cout这似乎“正常”工作
您已将函数定义为接受两个参数。声明第一个参数是为了指示引用的整数a
可以在f()
中更改,但b
不应更改
这两个参数都是通过引用传递的,您违反了const
的使用,因为更改的a
也被引用为b
这种行为是我在没有优化的情况下所期望的。(实际存储为m
的整数值在生成输出之前递增。)但是,根据编译器和选项的不同,可能会对此类别名进行不同的处理。在一般情况下,其行为可能未定义。此代码定义良好,没有问题
代码const int&b
表示:
b
指的是int
- 表达式
b
不能用于修改该int
但是,可以通过其他方式修改int
。例如,通过此处的a
。在编译f
时,编译器必须考虑到a
和b
可能都引用同一对象
某些编译器具有扩展,以指定函数参数(或其他变量)不应使用别名;例如,在MSVC++2015中,您可以编写:
void f(int & __restrict a, const int & __restrict b)
然后,编译器可能编译f
,假设&a!=&b
,也就是说,它可能为您的代码输出6 5
,这将是无声的未定义行为——编译器不需要诊断\u restrict
在编写一个函数时,如果该函数采用相同类型的多个引用或指针参数(不包括限定条件),或char
,则必须注意,某些参数可能会与其他参数同名。您可以通过以下方式之一进行传递:
- 编写代码,以便即使参数别名
- 包括一个类似于
if(&a==&b)return;
- 使用
\u restrict
并记录ONU由调用者承担,不允许别名
一种常见的情况是类的重载运算符=
。此函数需要支持编写x=x;
,即*此
可能会别名函数参数。有时,人们通过检查if(&A==this)来解决此问题return;
,有时他们会忽略该检查,但会设计实现,以便即使它们相等,它仍能工作。您要查找的术语是。我不确定“警告编译器”是什么意思-编译器完全知道这个问题。毕竟,它生成的代码产生了正确的输出,不是吗?为什么这是一个问题?您传入了一个可以修改的引用和一个不能修改的引用。它们仍然引用相同的数据,您只是无法通过b更改数据。您没有使数据常量只是对的引用数据。@Pemdas,这段代码容易出错。程序员容易出错。。lol@Pemdas将A
和B
视为矩阵运算,将f
视为矩阵运算。如果用户向其提供相同的矩阵,则函数将失败。例如inv(A,A)
。如何解决这个问题?那么你的意思是我在编写所有函数时都应该承担这个风险?是的。无论何时通过引用传递值,别名都可能是一个问题,编译器无法始终捕获。在这种情况下,调用例程定义了m
的实际存储,并通过引用将其作为非引用传递到例程中-常量。@igor提供了一个链接,可以很好地描述这个问题。第一个要点不是:“b
指的是const int
”“@CoffeeandCode不,这就是重点。b
指的是可以存储int
的存储。该存储可以是常量,也可以不是常量。对不起,我的意思是:第一个要点实际上不是:“b指逻辑上常量int
”?@CoffeeandCode否不会。引用不能是c.v限定符,因此c.v限定符必须引用引用的类型。
void f(int & __restrict a, const int & __restrict b)