ページ 1 / 1
代入演算子のオーバーロードの参照仮引数にconstがつく理由
Posted: 2018年12月09日(日) 20:26
by まいったね
以下のような代入演算子のオーバーロードがあります。
myclass &operator=(const myclass &ob)
参照仮引数にconstがついているのはなぜでしょうか。
myclass &operator=(myclass &ob)
以下のconstなしの代入演算子のオーバーロードを作成したし、main文で
o3=o1+o2;
と書いたところ、オペランドが一致する演算子=がありませんというエラーが出ました。
一方、
o2=o1;
と書いたところ、constなしでもエラーは出ませんでした。
Re: 代入演算子のオーバーロードの参照仮引数にconstがつく理由
Posted: 2018年12月09日(日) 22:26
by かずま
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がつく理由
Posted: 2018年12月09日(日) 23:52
by かずま
すみません。#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+ の定義が見たいので、
エラーが出たというソース全体を提示してもらえますか?
Re: 代入演算子のオーバーロードの参照仮引数にconstがつく理由
Posted: 2018年12月11日(火) 12:47
by YuO
左辺値参照 (以下,参照。右辺値参照はここでは扱わない) の初期化 (実引数による仮引数の初期化を含む) には,主に以下の制限があります。
- 初期化式が左辺値で,参照の型が初期化式と同じ型か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();
まいったね さんが書きました: ↑6年前
o3=o1+o2;
と書いたところ、オペランドが一致する演算子=がありませんというエラーが出ました。
o1+o2は通常右辺値です。
このため,o1+o2はconstでない参照を初期化することはできず,エラーになります。
まいったね さんが書きました: ↑6年前
o2=o1;
と書いたところ、constなしでもエラーは出ませんでした。
o1は左辺値であるため,constでない参照を初期化することができます。
このため,エラーにはなりません。
※左辺値と右辺値
右辺値参照・ムーブセマンティクス - cpprefjp - C++日本語リファレンスにざっくりとしつつ,端的な説明がありました。
cpprefjp さんが書きました:誤解を恐れずに言えば、右辺値とは名前をもたない一時的なオブジェクトである。
また、左辺値とは明示的に実態のある名前付きオブジェクトである。