问题分析
代码情况:
// 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++规定函数返回值不能作为左值
用一图表示: