引用指针的问题

时间:2010-09-23 18:57:33

标签: c++ reference

为什么这不能编译:

// 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; _

为什么地球下划线不会在列出错误的地方使用字体斜体?

5 个答案:

答案 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类中交换内部指针的两个临时副本,它会有什么意义?)

(至于你的第二个问题,我认为当你的行中出现其他格式修饰符(例如*)时斜体会被取消...)