为什么我可以使用非const变量来接收const函数

时间:2016-07-05 21:03:21

标签: c++

我正在测试的这个程序的结果对我来说没有意义:

class CC {
public:
    int a;
    CC();
    CC(int a);
    ~CC();
};

CC::CC() {
    this->a = 0;
}

CC::CC(int a) {
    this->a = a;
}

CC::~CC() {

}

const CC f() {
    CC cc(2);
    cout << &cc << endl;
    return cc;
}

int main() {
    CC cc = f();
    cc.a = 3;
    cout << &cc << " " << cc.a << endl;
}


result: // note the address are the same
0x7ffdd24b26e0
0x7ffdd24b26e0 3

我不明白为什么我可以在main()中使用非const变量来接收const返回值函数?内存地址是相同的,因此两个局部变量应该指向同一个对象。

g ++版本:

g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

4 个答案:

答案 0 :(得分:7)

  

为什么我可以在main()中使用非const变量来接收const返回值函数?

因为函数的返回值被复制到变量cc中。制作const对象的非const副本没有错;它不允许您修改const对象。

请将您想知道的任何其他内容重新发布为单独的问题。

答案 1 :(得分:0)

如果您无法在=的右侧使用常量,那么CC.a = 3;将是非法的。那将是疯狂的。使用常量的值肯定是合法的 - 你还会用常数做什么?

至于返回堆栈值,您将返回return执行时,该值已明确定义。该对象后来不再存在并不重要,因为您已经返回了它的值。

int foo()
{
    int i = 3;
    return i;
}

在这里,我们返回i的值,即返回3.没有错。

int& foo()
{
    int i = 3;
    return i;
}

这里我们返回对i的引用。但i已不复存在。那不好。

答案 2 :(得分:0)

FWIW,const CC的返回值与CC相同。

假设:

struct CC {};

const CC f() {
    return {};
}

g ++ 4.9.3生成的汇编代码与为:

生成的汇编代码完全相同
struct CC {};

CC f() {
    return {};
}

<强> PS

这可能是标准中我无法快速找到的地方。

答案 3 :(得分:0)

参考:Why function in c++ can return stack values

两个地址相同的原因是因为RVO。从语义上讲,main()中的变量'cc'仍然是f()中局部变量的副本。因为它只是原始对象的副本,所以将const返回值赋给非const变量是有意义的。