关键字“const”如何工作?

时间:2012-02-24 21:57:40

标签: c++ const

namespace pairDemo{

template<typename L, typename R>
class pair{
public:

    pair(const L& left,const R& right)
        :lft(left),rht(right)
    {
    }

    pair(const pair<L,R>& p)
        :lft(p.lft),rht(p.rht)
    {
    }

    L left() const{
        return lft;
    }
    R right() const{
        return rht;
    }

    void left(const L& left){
        lft = left;
    }
    void right(const R& right){
        rht = right;
    }
private:
    L lft;
    R rht;
};
}

// --------------------------------------------- ------

#include "pairTemp.h"
#include <iostream>
using namespace std;

pairDemo::pair<int, double> func(int x, double y){
    pairDemo::pair<int, double> temp(x*2, x+y);
    return temp;
}

int main(){
    int x = 2; double y = 3.55;
    pairDemo::pair<int, double> myPair = func(x,y);
    cout << myPair.left() << myPair.right();
}

我有一个问题,即构造函数参数,如果我不声明“const”,函数func()将会出错。我不知道为什么,任何人都可以帮助我。

4 个答案:

答案 0 :(得分:2)

由于您将x * 2和x + y传递给构造函数,因此必须将引用声明为const(即只读)。

如果你传递一个非const(即读写)引用,那么函数的代码将能够修改引用以更改传入的任何值。如果你传递x,这是有意义的,y,因为代码可以想象地更新这些值。

但是在这种情况下,更改x * 2或x + y的值没有意义,编译器坚持认为引用是const。

答案 1 :(得分:1)

pair(const L& left,const R& right)
        : lft(left), rht(right)
{
}

pairDemo::pair<int, double> func(int x, double y) 
{
    pairDemo::pair<int, double> temp(x*2, x+y);
    return temp;                //   ^^^  ^^^
}                               //  temporaries here

您的构造函数通过引用获取其参数。在func中,您将临时对象传递给此构造函数。临时对象只能绑定到 const 引用,这就是为什么在删除const时出现错误的原因。如果选择按值传递参数,则可以省略const限定符。

答案 2 :(得分:1)

是的,如果您的参数类型为int &,则无法传递参数x * 2。拥有非const引用参数允许修改参数,如果您决定忽略这些修改(如果有的话),则需要明确地这样做。

至于将x * 2传递给const int &,它可能有点奇怪,但实际发生的是创建一个新的临时变量,分配x * 2和< em> 变量是传递给函数的东西。在这种情况下,自动创建临时文件没有问题,因为它的值无论如何都不会改变(这就是为什么你有const,不是吗?)。

答案 3 :(得分:1)

如果从构造函数const中删除pair::pair(const L& left,const R& right),则代码pairDemo::pair<int, double> temp(x*2, x+y);将无效,因为x*2的结果被禁止绑定到{{1}并且L& left被禁止绑定到x+y

C ++有这个规则,因为设计人员认为非const引用类型的函数参数应该表明函数可以更改值,并且该更改应该对调用者可见。

考虑:

R& right

如果有人意外使用void foo(int &i) { i = 3; } foo(x); // sets x to 3 foo(1); // sets 1 to 3??? prohibited foo1x+y这样的临时来电话x*2,这可能会造成混淆,因此C ++决定做安全事情而不允许这些要编译。

C ++ 11增加了'rvalue references',它们有一些不同的规则。

void bar(int &&i) { // && means 'rvalue reference' 
    i = 3;
}

bar(1); // sets 1 to 3!
bar(x); // prohibited.

rvalue引用应该意味着该函数正在获得一个临时值,并且它对它的任何作用都不会影响外部世界。现在的危险在于,一个采用右值参考的函数会被意外地用非临时函数调用。因此,规则试图禁止您传递非临时值,如x