为什么这不能编译:
// RefToPointers.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using std::cout;
class T
{
public:
T(int* value):data_(value)
{
}
int* data_;
int* getData_()
{
return data_;
}
int getValue()//<----------Here I do not return by ref
{
return *data_;
}
};
void fnc(const int*& left, const int*& right )//<------Doesn't work even though
//it is identical to the example below just type is different. Why?
{
const int* tmp = left;
left = right;
right = tmp;
}
void fnc(const int& left,const int& right)//<---Here I pass by ref
{
}
int _tmain(int argc, _TCHAR* argv[])
{
//int* one = new int(1);
//int* two = new int(2);
//cout << "Pointers before change:" << *one << '\t' << *two << '\n';
//fnc(one,two);
//cout << "Pointers before change:" << *one << '\t' << *two << '\n';
T one(new int(1));
T two(new int(2));
fnc(one.getData_(),two.getData_());//<---This do not work
fnc(one.getValue(),two.getValue());//<<------This still works even thoug I'm
//returning by value and fnc is taking args by ref. Why does it work with int
//by not with int*?
return 0;
}
我收到了以下错误:
_error C2664:'fnc':无法将参数1从'int *'转换为'int *&amp; _
为什么地球下划线不会在列出错误的地方使用字体斜体?
答案 0 :(得分:1)
int* getData_()
此函数返回一个r值,但int*&
需要一个l值,因此编译器会抱怨。您还应在int*&
中返回getData_()
。
int*& getData_() { return data_; }
同时,const int&
可以接受右值,因此第二个fnc
可以正确编译。 const
引用不与(可变)引用完全相同。
(当然,最好还提供一个const版本。
int* const& getData_() const { return data_; }
// or: int* getData_() const { return data_; }
另请注意,如果new
内容没有delete
,您的程序会泄漏内存。)
答案 1 :(得分:1)
getData()
返回右值。你不能引用右值指针。
您有两种选择:
1)通过fnc()
左值:
int* lhs = one.getData_();
int* rhs = two.getData_();
fnc(lhs, rhs);
2)或者,既然你传递了指针引用,它实际上与指针本身的大小相同,为什么不直接传递指针?
void fnc(int* left, int* right )
{
int* tmp = left;
left = right;
right = tmp;
}
编辑:
关于左值和左值的更多信息。 “左值”用于表示“可以在=
操作左侧的表达式”。 rvalue实际上是反过来的:rvalue是=
操作左边的任何表达式。
事情比现在复杂得多,但这仍然是理解左值和左值的好方法。
现在,请考虑以下代码:
int val()
{
return 42;
}
int main()
{
int* p = &val();
}
val()
按值返回int
- 换句话说,它返回一个未命名的临时值。你能不能拿那个临时的地址?
你可能会想,“好吧,是的,为什么不呢?”但答案其实是没有,你不能拿临时的地址。原因与该临时的生命周期有关。它的范围仅限于创建它的表达式。换句话说:val()
。只要val()
被完全评估,临时就不再存在。实际上,它从堆栈上掉下来。在评估int* p = &
时,临时性早已消失。没有什么可以拿地址了。
这基本上就是为什么你不能取rvalue的地址,因为你无法获得对rvalue地址的引用。
答案 2 :(得分:0)
您只能对变量进行引用(&amp;),而不是对函数的返回值进行修改,当您更改它时,更改将在何处进行?
答案 3 :(得分:0)
因为getData_()返回int *而不是int *&amp;。这意味着您将临时值作为实际参数传递给fnc,而临时值不能转换为(可变)引用。更改getData_()以返回int *&amp;。
答案 4 :(得分:0)
请注意getData_()
按值返回指针。这意味着临时用于保存来自调用的返回指针。你不能创建(非常量)对temporaries的引用(如果要在T
类中交换内部指针的两个临时副本,它会有什么意义?)
(至于你的第二个问题,我认为当你的行中出现其他格式修饰符(例如*)时斜体会被取消...)