C++ 将返回的引用直接传递给函数
C++ passing returned reference directly to function
你能看看这两个例子并解释一下为什么第一次尝试打印结果给了我错误的数字吗?
第一个例子(printRes 通过指针传递 x):
int& getInt(int x){
x++;
cout << "int " << x << endl;
return x;
}
void printRes(int *x){
cout << "res " << *x << endl;
}
int main()
{
int t = getInt(5);
printRes(&getInt(5)); // first attemp
printRes(&t); // second attemp
return 0;
}
第二个示例(printRes 通过引用传递 x):
int& getInt(int x){
x++;
cout << "int " << x << endl;
return x;
}
void printRes(int &x){
cout << "res " << x << endl;
}
int main()
{
int t = getInt(5);
printRes(getInt(5)); // first attemp
printRes(t); // second attemp
return 0;
}
结果:
int 6
int 6
res 2686640
res 6
当我按值传递 'x' 时,它工作正常,但我的目标是得到这样的东西:
- 函数 getInt 创建对象,将其放入向量中(所以我只调用 v.emplace_back())和 returns 引用当前添加的对象 (v.back())
- getInt 返回的值被传递给 printRes,它用文件中的值填充对象
我不想创建诸如 't' 之类的时间变量,而是将向量元素直接传递给 printRes 函数,但在我更扩展的情况下,我在析构函数中崩溃(或有时在一些随机位置)。
为什么第一次调用 printRes() 给你错误的结果是因为 getInt() 有一个严重的缺陷。
问题是 getInt() return 是对局部变量的引用,这在 C++ 中是行不通的。在 getInt() returns 的那一刻,变量 x 不再存在,并且对该变量的任何引用都变得无效。结果是 printRes() 在行中接收到的指针:
printRes(&getInt(5));
很可能指向胡说八道。第二个例子也有同样的论点。
第二次调用 printRes() 给你正确结果的原因是运气。当在行中 returned 无效引用时:
int t = getInt(5);
变量 t 被初始化为 x 的值,因为它发生在 getInt() returns 之后,存储 x 的内存还没有被覆盖。
无论如何,return引用是您应该谨慎的事情。查看 Is the practice of returning a C++ reference variable, evil?
做你想做的事情的一种方法是定义一个 vector v ,它在 getInt() 中不是本地的(因此它可以存在于函数的范围之外)并且 return 一个迭代器代替。像这样:
#include <iostream>
#include <vector>
using namespace std;
vector<int> v;
vector<int>::iterator getInt(int x){
x++;
cout << "int " << x << endl;
v.emplace_back(x);
return --v.end(); // end() points to after last element.
// Decrement to get the last element
}
void printRes(vector<int>::iterator i){
cout << "res " << *i << endl;
*i = 99; //set the element to a new value if you want
}
int main()
{
printRes(getInt(5));
return 0;
}
请注意,每当使用 v.emplace_back()(或类似函数)时,从 getInt() 编辑的迭代器 return 就会失效,因此您不应将其存储太久。但是,像这里一样立即使用它是可以的。
你能看看这两个例子并解释一下为什么第一次尝试打印结果给了我错误的数字吗?
第一个例子(printRes 通过指针传递 x):
int& getInt(int x){
x++;
cout << "int " << x << endl;
return x;
}
void printRes(int *x){
cout << "res " << *x << endl;
}
int main()
{
int t = getInt(5);
printRes(&getInt(5)); // first attemp
printRes(&t); // second attemp
return 0;
}
第二个示例(printRes 通过引用传递 x):
int& getInt(int x){
x++;
cout << "int " << x << endl;
return x;
}
void printRes(int &x){
cout << "res " << x << endl;
}
int main()
{
int t = getInt(5);
printRes(getInt(5)); // first attemp
printRes(t); // second attemp
return 0;
}
结果:
int 6
int 6
res 2686640
res 6
当我按值传递 'x' 时,它工作正常,但我的目标是得到这样的东西:
- 函数 getInt 创建对象,将其放入向量中(所以我只调用 v.emplace_back())和 returns 引用当前添加的对象 (v.back())
- getInt 返回的值被传递给 printRes,它用文件中的值填充对象
我不想创建诸如 't' 之类的时间变量,而是将向量元素直接传递给 printRes 函数,但在我更扩展的情况下,我在析构函数中崩溃(或有时在一些随机位置)。
为什么第一次调用 printRes() 给你错误的结果是因为 getInt() 有一个严重的缺陷。
问题是 getInt() return 是对局部变量的引用,这在 C++ 中是行不通的。在 getInt() returns 的那一刻,变量 x 不再存在,并且对该变量的任何引用都变得无效。结果是 printRes() 在行中接收到的指针:
printRes(&getInt(5));
很可能指向胡说八道。第二个例子也有同样的论点。
第二次调用 printRes() 给你正确结果的原因是运气。当在行中 returned 无效引用时:
int t = getInt(5);
变量 t 被初始化为 x 的值,因为它发生在 getInt() returns 之后,存储 x 的内存还没有被覆盖。
无论如何,return引用是您应该谨慎的事情。查看 Is the practice of returning a C++ reference variable, evil?
做你想做的事情的一种方法是定义一个 vector v ,它在 getInt() 中不是本地的(因此它可以存在于函数的范围之外)并且 return 一个迭代器代替。像这样:
#include <iostream>
#include <vector>
using namespace std;
vector<int> v;
vector<int>::iterator getInt(int x){
x++;
cout << "int " << x << endl;
v.emplace_back(x);
return --v.end(); // end() points to after last element.
// Decrement to get the last element
}
void printRes(vector<int>::iterator i){
cout << "res " << *i << endl;
*i = 99; //set the element to a new value if you want
}
int main()
{
printRes(getInt(5));
return 0;
}
请注意,每当使用 v.emplace_back()(或类似函数)时,从 getInt() 编辑的迭代器 return 就会失效,因此您不应将其存储太久。但是,像这里一样立即使用它是可以的。