web-dev-qa-db-ja.com

一時オブジェクトのアドレスを取得する

§5.3.1単項演算子、セクション3

単項&演算子の結果は、そのオペランドへのポインターです。 オペランドは左辺値でなければなりませんまたは修飾ID。

この文脈で「あるべき」とは正確にはどういう意味ですか?一時的なアドレスを取得するのはエラーだということですか? g ++は警告を表示するだけなので、疑問に思っていましたが、comeauは次のプログラムのコンパイルを拒否します。

#include <string>

int main()
{
    &std::string("test");
}

g ++ 警告taking address of temporary

コモーエラーexpression must be an lvalue or a function designator

誰かがMicrosoftコンパイラまたは他のコンパイラを持っていて、このプログラムをテストできますか?

27
fredoverflow

標準語で「しなければならない」という言葉は、厳格な要件を意味します。したがって、はい、コードは非左辺値にaddress-of演算子を適用しようとするため、形式が正しくありません(エラーです)。

ただし、ここでの問題は、一時のアドレスを取得しようとする試みではありません。ここでも、問題は非左辺値のアドレスを取ることです。一時オブジェクトは、その一時オブジェクトを生成する式、またはその一時オブジェクトへのアクセスを提供する式に応じて、左辺値または非左辺値になります。あなたの場合、std::string("test")-非参照型にキャストされた関数型スタイルがあります。これは、定義上、非左辺値を生成します。したがって、エラー。

一時オブジェクトのアドレスを取得したい場合は、たとえば、これを行うことで制限を回避できます。

const std::string &r = std::string("test");
&r; // this expression produces address of a temporary

結果のポインタは、一時的なものが存在する限り有効なままです。一時オブジェクトのアドレスを合法的に取得する方法は他にもあります。あなたの特定の方法がたまたま違法であるというだけです。

26
AnT

C++標準で「しなければならない」という言葉が使用されている場合、それは「死の苦痛を伴う必要がある」という意味です。実装がこれに従わない場合、それは誤りです。

5
anon

非推奨の/ Ze(拡張機能が有効)オプションを使用すると、MSVCで許可されます。以前のバージョンのMSVCで許可されていました。すべての警告を有効にして診断を生成します。

警告C4238:非標準の拡張子が使用されました:クラス右辺値が左辺値として使用されました。

/ Zaオプションが使用されていない限り(ANSI互換性を強制する)、次のようになります。

エラーC2102: '&'にはl値が必要です

3
Hans Passant

&std::string("test");は、関数呼び出しの戻り値のアドレスを要求しています(この関数がctorであるという事実は無関係であるため、無視します)。あなたが何かにそれを割り当てるまで、それはアドレスを持っていませんでした。したがって、それはエラーです。

1
James Curran

C++標準は、実際には準拠したC++実装の要件です。ある場所では、適合実装が受け入れなければならないコードと、適合実装が診断を与えなければならないコードを区別するために書かれています。

したがって、この特定のケースでは、適合コンパイラ必須右辺値のアドレスが取得された場合に診断を提供します。どちらのコンパイラもそうなので、この点で準拠しています。

この標準では、特定の入力によって診断が行われた場合、つまり警告が有効な診断である場合に、実行可能ファイルの生成が禁止されていません。

1
MSalters

私は標準の専門家ではありませんが、確かに私には間違いのように聞こえます。 g ++は、実際にはエラーであるものに対してのみ警告を出すことがよくあります。

0
Hans W

ユーザー定義の変換

struct String {
    std::string str;

    operator std::string*() {
        return &str;
    }
};

std::string *my_str = String{"abc"};
0
SPapiernik