titus
titus

Reputation: 49

How keyword "const" work?

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();
}

I have a question that the constructor arguments, If I do not declare "const", the function func() will have a error. I dont why, and anyone can help me out.

Upvotes: 0

Views: 231

Answers (4)

bames53
bames53

Reputation: 88155

If you remove the consts from the constructor pair::pair(const L& left,const R& right) then the code pairDemo::pair<int, double> temp(x*2, x+y); won't work because the result of x*2 is prohibited from binding to L& left and x+y is prohibited from binding to R& right.

C++ has this rule because the designers felt that function parameters of non-const reference types should indicate that the the function can change the value, and that that change should be visible to the caller.

consider:

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

foo(x); // sets x to 3
foo(1); // sets 1 to 3??? prohibited

This could cause confusion if someone accidentally calls foo with a temporary like 1 or or x+y or x*2, so C++ decides to do the safe thing and not allow these to compile.

C++11 adds 'rvalue references' which have some different rules.

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

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

rvalue references are supposed to mean that the function is getting a temporary value and whatever it does with it will not affect the outside world. Now the danger is that a function taking an rvalue reference would accidentally be called with a non-temporary. Therefore the rules try to prohibit you from passing in a non-temporary value like x.

Upvotes: 1

user743382
user743382

Reputation:

Yes, if you have a parameter of type int &, you cannot pass an argument x * 2. Having a non-const reference parameter allows modifications of the argument, and if you decide to ignore those modifications (if any), you need to do so explicitly.

As for passing x * 2 to const int &, it may be a bit strange that that works, but what actually happens is that a new temporary variable is created, assigned x * 2, and that variable is what gets passed to the function. In this case, there isn't a problem with automatically creating a temporary, because its value won't be changed anyway (that's why you have const, is it not?).

Upvotes: 1

jrok
jrok

Reputation: 55395

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

Your constructor takes its parameters by reference. In func, you're passing temporary objects to this constructor. Temporary objects can only bind to const references, that's why you're getting an error if you remove const. If you chose to pass the parameters by value, you could omit const qualifiers.

Upvotes: 1

vmpstr
vmpstr

Reputation: 5211

Since you are passing x*2 and x+y to the constructor, the references must be declared as const (ie read-only).

If you are passing a non-const (ie read-write) reference, then the code of the function would be able to modify the reference to change the value of whatever was passed in. This makes sense if you are passing x, y, because the code could conceivably update those values.

But in this case, changing the value of either x*2 or x+y does not make sense, the compiler insists that the reference be const.

Upvotes: 2

Related Questions