13

C ++03§4.2N°1:
「NTの配列」または「Tの未知の境界の配列」タイプの左辺値または右辺値は、「Tへのポインター」タイプの右辺値に変換できます。結果は、配列の最初の要素へのポインターです。

このステートメントで長い間混乱していたのは、配列型の右辺値が何を意味するのかよく理解していなかったということです。つまり、型が配列で結果が右辺値である式を思い付くことができませんでした。私はこのスレッドを読みました。これは基本的に同じ質問をし、受け入れられた答えは「いいえ、配列型の右辺値はありません」です。これには矛盾があるのではないかと思います。

C ++03§5.2.5N°4:(式E1.E2に関するもの)
E2が非静的データメンバーであり、E1のタイプが「cq1vq1 X」であり、E2のタイプが「cq2」である場合vq2 T」、式は、最初の式で指定されたオブジェクトの指定されたメンバーを指定します。E1が左辺値の場合、E1.E2は左辺値です。

それ以外の場合は右辺値であると思います(E2が参照ではない場合、その場合はでカバーされ§5.2.5 N°3ます)。したがって...

struct A
{
   int a[4];
};
A f()
{
   A a;
   return a; 
}
int main()
{
   f().a; //I think this is an rvalue of array type...
}

ここに2つのオプションがあります。オプション1
:正解です、万歳、イェーイ、かっこいいです。この場合、問題は次のとおりです。他の例はありますか?
オプション2:私は間違っています。この場合の質問は次のとおりです。これは標準の欠陥ですか?

1についてはわかりませんが、2については本当に疑問です。なぜなら、関数からポインターへの変換について話すとき、関数型の左辺値だけに言及しているからです(明らかに、そのような右辺値がないことを認めています)。したがって、彼らは配列型の右辺値を考えていた可能性が非常に高いです。

ですから、基本的に私の質問は、配列型の右辺値の例を思いついたかどうかです。そうでない場合は、有効なものを提供してください。

4

2 に答える 2

12

はい。それで合っています。式は配列型の右辺値です。これは欠陥ではありません。委員会はそれを知っています。また、配列型の左辺値のポインターへの変換のみを許可するC89の一般的な問題でもありました。結果として、のような配列にインデックスを付けたり、逆参照したりすることはできませんでしたf().a。C99はこれを修正し、C++には問題はありません。

右辺値であるかどうかは、式がオブジェクトを表すかどうかとは無関係であることに注意してください。C ++ 03は、配列型の右辺値式がオブジェクトを示していると誤って省略しています。これは、C ++ 0xでDR#450によって修正されました。

(明らかに、そのような右辺値がないことを認めます)

実際には関数型の右辺値があります。これらは、クラスメンバーアクセス式で示される非静的メンバー関数で発生します

struct A { void f(); };

/* A().f is an rvalue of type "void()" */
int main() { A().f(); }
于 2010-10-30T10:13:50.130 に答える
-3

Aは右辺値です。その中の配列はそうではありません。その一時オブジェクトにメソッドチェーンがある場合を想像してみてください。その中の変数は、複数のメソッド呼び出しと戻りの間存続し、他の関数への参照(チェーンの期間中有効)を渡す場合があります。これらの関数は、右辺値で呼び出されることを事前に知ることはできません。

ドラフトの最新バージョンでは、右辺値/左辺値*thisの関数をオーバーロードできます。ただし、それでも、右辺値参照は右辺値と呼ばれる内容を作成しません。また、コンパイラが現在これをサポートしているかどうかは完全にはわかりません。MSVCはサポートしていません。

実際、decltypeを使用すると、コンパイラがその配列を左辺値と呼んでいることを簡単に判断できます。

検討:

template<typename A, typename B> auto sum(A&& a, B&& b) -> decltype(std::forward<A>(a) + std::forward<B>(b)) {
    return std::forward<A>(a) + std::forward<B>(b);
}

それがdecltypeの目的であり、左辺値と右辺値を最も明確に区別します。または、次のことを考慮してください。

int main()
{
    auto var = f().a;
}

Varはint*です。f()。aはすぐに死ぬので、これはすぐに失敗します。それについての私の当面の意見はわかりませんが、それは確かに右辺値には有効ではありません。

于 2010-10-30T10:07:22.267 に答える