代入演算子のオーバーロードの参照仮引数にconstがつく理由

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
まいったね

代入演算子のオーバーロードの参照仮引数にconstがつく理由

#1

投稿記事 by まいったね » 5年前

以下のような代入演算子のオーバーロードがあります。
myclass &operator=(const myclass &ob)
参照仮引数にconstがついているのはなぜでしょうか。
myclass &operator=(myclass &ob)
以下のconstなしの代入演算子のオーバーロードを作成したし、main文で
o3=o1+o2;
と書いたところ、オペランドが一致する演算子=がありませんというエラーが出ました。
一方、
o2=o1;
と書いたところ、constなしでもエラーは出ませんでした。

かずま

Re: 代入演算子のオーバーロードの参照仮引数にconstがつく理由

#2

投稿記事 by かずま » 5年前

const myclass &ob の場合、ob = o1; は実行できません。const だから。
myclass &ob: ob = o1; が実行できます。

o2 = o1; の o1 は変数であり、変更可能です。
o3 = o1 + o2; の o1 + o2 の演算結果は一時オブジェクトであり、
変更可能な変数ではありません。
o1 + o2 = o3; とは書けないでしょう。

const myclass &ob の ob は o1 + o2 への参照になれますが、
myclass &ob の ob は o1 + o2 への参照になれません。

かずま

Re: 代入演算子のオーバーロードの参照仮引数にconstがつく理由

#3

投稿記事 by かずま » 5年前

すみません。#2 の説明は間違っていました。
クラスの定義の仕方により、
o1 + o2 = o3; がエラーにならないようにもできます。

コード:

#include <iostream>

class myclass {
	int v;
public:
	myclass(int x = 0) : v(x) {}
	operator int() const { return v; } 
	myclass& operator=(myclass& x) { v = x.v; return *this; }
	myclass operator+(const myclass& x) const { return myclass(v + x.v); }
};

int main()
{
	myclass o1(3), o2(5), o3(7);
	o1 + o2 = o3;
	std::cout << o1 << " " << o2 << " " << o3 << "\n"; 
}
operator+ の定義が見たいので、
エラーが出たというソース全体を提示してもらえますか?

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: 代入演算子のオーバーロードの参照仮引数にconstがつく理由

#4

投稿記事 by YuO » 5年前

左辺値参照 (以下,参照。右辺値参照はここでは扱わない) の初期化 (実引数による仮引数の初期化を含む) には,主に以下の制限があります。
  • 初期化式が左辺値で,参照の型が初期化式と同じ型かconstが追加された型である

    コード:

    class B {};
    B b;
    const cb;
    B& rb = b;
    const B& crb1 = b;
    const B& crb2 = cb;
  • 初期化式が左辺値で,参照の型が初期化式の基底型かconstが追加された基本型である

    コード:

    class B {};
    class D : B {};
    
    D d;
    const D cd;
    B& rb = d;
    const B& crb1 = d;
    const B& crb2 = cd;
  • 参照の型が初期化式にconstを追加した型である

    コード:

    class B {};
    const B& rb = B();
  • 参照の型が初期化式の基底型にconstを追加した型である

    コード:

    class B {};
    class D : B {};
    
    const B& rb = D();

まいったね さんが書きました:
5年前
o3=o1+o2;
と書いたところ、オペランドが一致する演算子=がありませんというエラーが出ました。
o1+o2は通常右辺値です。
このため,o1+o2はconstでない参照を初期化することはできず,エラーになります。

まいったね さんが書きました:
5年前
o2=o1;
と書いたところ、constなしでもエラーは出ませんでした。
o1は左辺値であるため,constでない参照を初期化することができます。
このため,エラーにはなりません。


※左辺値と右辺値
右辺値参照・ムーブセマンティクス - cpprefjp - C++日本語リファレンスにざっくりとしつつ,端的な説明がありました。
cpprefjp さんが書きました:誤解を恐れずに言えば、右辺値とは名前をもたない一時的なオブジェクトである。
また、左辺値とは明示的に実態のある名前付きオブジェクトである。

返信

“C言語何でも質問掲示板” へ戻る