> 文章列表 > 非常量引用只能绑定到左值

非常量引用只能绑定到左值

非常量引用只能绑定到左值

问题分析

代码情况:

// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
using namespace std;
vector<int> fun1()
{vector<int> ver1;for (int i = 0; i < 10 ; i++){ver1.push_back(i);}return ver1;
}
void fun2(vector<int> &b)
{for (int i = 0; i < 10 ; i++){printf("b=%d,", b.at(i));}cout << "\\n";}
int main()
{fun2(fun1());std::cout << "Hello World!\\n";
}// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

编译情况:

已启动生成...
1>------ 已启动生成: 项目: ConsoleApplication1, 配置: Debug x64 ------
1>ConsoleApplication1.cpp
1>E:\\project2023\\example\\ConsoleApplication1.cpp(27,5): error C2664:void fun2(std::vector<int,std::allocator<int>> &): 无法将参数 1 从“std::vector<int,std::allocator<int>>”转换为“std::vector<int,std::allocator<int>> &1>E:\\project2023\\example\\ConsoleApplication1.cpp(27,14): message :常量引用只能绑定到左值
1>E:\\project2023\\example\\ConsoleApplication1.cpp(16,6): message : 参见“fun2”的声明
1>E:\\project2023\\example\\ConsoleApplication1.cpp(27,5): message : 尝试匹配参数列表“(std::vector<int,std::allocator<int>>)”时
1>已完成生成项目“ConsoleApplication1.vcxproj”的操作 - 失败。
========== 生成: 0 成功,1 失败,0 最新,0 已跳过 ==========
========= 生成 开始于 11:34 AM,并花费了 00.838==========

更改为:

int main()
{//fun2(fun1());vector<int> ver2 = fun1();fun2(ver2);std::cout << "Hello World!\\n";
}

运行情况
非常量引用只能绑定到左值

问题总结

先解释左值和右值的区别:
从字面意思看,左右值就是在“=”两端的变量或表达式,但其实不是这样的。
左值(Location Value):并不是left_value,指的是可以寻址。指的是如果一个表达式可以引用到某一个对象,并且这个对象是一块内存空间且可以被检查和存储,
那么这个表达式就可以作为一个左值。
右值(Read Value):也就是可读。指的是引用了一个存储在某个内存地址里的“数据”。
上面错误的例子中的fun1()返回了一个vector,这一个vector是一个临时对象,临时对象都是常量,不能作为左值,只能用const引用,不能改变值。
那为什么常量没有不能作为左值?
因为常量没有地址
为什么常量没有地址?
常量不同于变量的在运行期分配内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用。
常量本就是数据,与内存地址没有关系
也可以这样理解,C++规定函数返回值不能作为左值

用一图表示:
非常量引用只能绑定到左值