[解決済み】なぜ、constでない参照は一時的なオブジェクトにバインドできないのでしょうか?
質問
一時的なオブジェクトへのconstでない参照を取得することができないのはなぜですか?
どの関数
getx()
を返すのでしょうか?明らかにC++標準では禁止されています。
しかし、私はこのような制限の目的に興味があります。
参照ではない
を標準化した。
struct X
{
X& ref() { return *this; }
};
X getx() { return X();}
void g(X & x) {}
int f()
{
const X& x = getx(); // OK
X& x = getx(); // error
X& x = getx().ref(); // OK
g(getx()); //error
g(getx().ref()); //OK
return 0;
}
- オブジェクトのライフタイムが原因でないことは明らかです。 オブジェクトへの常時参照は 禁止されていない は、C++標準によって
-
上記のサンプルでは、定数でない関数の呼び出しが許可されているため、一時的なオブジェクトが定数でないことは明らかです。例えば
ref()
は一時的なオブジェクトを変更することができます。 -
さらに
ref()
を使えば、コンパイラーをだまして、この一時的なオブジェクトへのリンクを取得することができ、これで問題は解決です。
おまけに
const参照に一時的なオブジェクトを代入すると、このオブジェクトの寿命が延びるそうです"const参照以外については何も言われていませんが"。 私の 追加質問 . 次の代入は、一時的なオブジェクトの寿命を延長しますか?
X& x = getx().ref(); // OK
解決方法は?
ここから Visual C++のブログでrvalueの参照について書かれた記事 :
<ブロッククオート... C++は、あなたが誤って テンポラリーを変更しても、直接 に対してconstでないメンバ関数を呼び出す 変更可能なr値は明示的であり、そのため 許される.
基本的に、テンポラリは一時的なオブジェクトであり、今にも死んでしまうという理由から、変更しようとしないほうがよいでしょう。コンストラストでないメソッドを呼び出すことが許されているのは、自分が何をしているかを知っていて、それを明示する限り、いくつかの "愚かな" を行うことが許されているからです(例えば reinterpret_cast を使うなど)。しかし、temporaryをconstでない参照にバインドしてしまうと、temporaryであることを完全に忘れてしまったために、オブジェクトの操作が消えてしまうということがあり得ます。
私があなたなら、関数の設計を見直しますね。なぜg()は参照を受け入れるのでしょうか?パラメータを変更するのでしょうか?もしそうなら、なぜtemporaryを渡そうとするのでしょうか?なぜ、getx()はtemporaryを返すのですか?あなたの実際のシナリオと、あなたが達成しようとしていることを私たちと共有すれば、それを行う方法についていくつかの良い提案を得ることができるかもしれません。
言語に逆らったり、コンパイラーを騙したりしても、問題が解決することはほとんどなく、たいていの場合、問題が発生します。
編集:コメント中の質問に対応します。 1)
X& x = getx().ref(); // OK when will x die?
- これはまさに私が言っている「言語に反する」ということなので、私は知りませんし、気にしません。言語では、quot;temporaryは文の終わりで死ぬ。ただし、const参照に束縛されている場合は、その参照がスコープ外に出たときに死ぬ。この規則を適用すると、xはconst参照に束縛されていない(コンパイラはref()が何を返すか知らない)ので、次の文の始めにはすでに死んでいるようです。ただし、これは単なる推測に過ぎない。
2) 私は目的を明確に述べました:テンポラリーを修正することは許されていません、なぜなら意味がないからです(C++0xのr値参照を無視する)。C++0xのrvalueの参照を無視したもの)。
3) さて、もし私の言うとおりなら
X& x = getx().ref();
が文末に死ぬと、問題は明白です。
とにかく、あなたの質問とコメントからすると、これらの余分な答えでさえ、あなたを満足させることはできないと思います。C++委員会は、テンポラリを変更するのは意味がないと判断し、非const参照へのバインディングを禁止しました。このとき、コンパイラの実装や歴史的な問題が絡んでいたかもしれません。しかし、ある特殊なケースが発生し、どう考えてもconstでないメソッドを呼び出して直接変更することを認めることになった。でも、それは例外で、一般的にはテンポラリの改変は許されない。そう、C++はそのくらい変なことが多いのです。
関連
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] std::string を const char* または char* に変換する方法
-
[解決済み] 変数を参照渡しする方法を教えてください。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] 配列のベクトルを扱う正しい方法