2012-07-18 6 views
12

私はいくつかのC++の静的解析ルールを実装していて、そのうちの一つは、関数の参照パラメータへの参照やポインタを返すから機能を禁止し、次のIEは、すべての非準拠しています:このC++静的解析ルールは意味を持ちますか?

int *f(int& x) { return &x; } // #1 
const int *g(const int& x) { return &x; } // #2 
int& h(int& x) { return x; } // #3 
const int& m(const int& x) { return x; } // #4 

このために与えられる正当化は、「参照パラメータが一時オブジェクトであるかパラメータへの参照であろうと、実装定義の振る舞い」であるということです。

しかし、C++のストリーム演算子はこのように書かれているので、私はこれに戸惑います。

std::ostream& operator<<(std::ostream& os, const X& x) { 
    //... 
    return os; 
} 

私は、C++のストリーム演算子は一般的に実装定義の振る舞いを示さないと思うので、どうしていますか?

現時点で私が理解しているところでは、一時参照は非const参照にバインドできないので、#1と#3は明確に定義されています。int& xは、関数の範囲を超えて生涯があるため、そのオブジェクトへのポインタや参照を返すのは問題ありません。一時的なものがconst int& xにバインドされている可能性があるので、私は#2がドギーになると予想します。その場合、そのアドレスを取ろうとすると悪い計画に見えるでしょう。私は#4について確信が持てません - 私の直感はそれも潜在的にドギーですが、わかりません。特に、私は次のような場合に何が起こるかについては明らかではないよ:(#1は間違いなく悪いスタイルですが)

const int& m(const int& x) { return x; } 
//... 
const int& r = m(23); 
+0

MSVC++を使用していますか? – Nawaz

+0

@Nawaz:私は大規模なコードベースでクエリを書くのに.QLを使用しています:)私はそれがどのコンパイラであろうと、私は理想的にはプラットフォームに依存しない答えを探しているとは思わないと思います。 –

+2

なぜ私はMSVC++が一時的なものが非const参照にバインドすることを可能にするコンパイラの拡張機能を提供しているので尋ねました。また、Microsoftの静的分析ツールを使用している場合は、この拡張も考慮する必要があります。 – Nawaz

答えて

8

あなたが言うように、#1、#3が細かいです。

#4は同じ理由でドッジーです。 const参照をその存続期間を過ぎた一時的なものに伝播させることができます。

のは確認してみましょう:

#include <iostream> 

struct C { 
    C() { std::cout << "C()\n"; } 
    ~C() { std::cout << "~C()\n"; } 
    C(const C &) { std::cout << "C(const C &)\n"; } 
}; 

const C &foo(const C &c) { return c; } 

int main() { 
    const C &c = foo(C()); 
    std::cout << "c in scope\n"; 
} 

この出力:右辺値参照のオーバーロードもある場合はC++ 11では

C() 
~C() 
c in scope 
+0

ありがとう - 私はこの種のことをすることによって一時的な生涯が延長されるかどうか分からなかった。答えのようなものは確かに会社ではない。 –

+0

とストリームオペレータはどうですか? – Arne

+3

@Arne:彼らは非const参照を受け取り、返すので、問題ありません。 –

1

、#2、#4を安全にすることができます。したがって:

const int *get(const int &x) { return &x; } 
const int *get(const int &&x) { return nullptr; } 

void test() { 
    const int x = 0; 
    const int *p1 = get(x); // OK; p1 is &x. 
    const int *p2 = get(x+42); // OK; p2 is nullptr. 
} 

だからこそ、彼らはドギーですが、プログラマーが自分が何をしているか知っていれば、安全に使用できます。これを禁止するのは大変です。

(おそらく、const rvalue参照のオーバーロードがプライベートになっていたり、定義されていなかったり、コンパイル時やリンク時にエラーが発生した場合は安全かもしれません。参照を返すのに良いことは何もなく、言語ではnullへの参照が許可されていません)。

+0

ありがとう、良い点、特に将来のために。この文脈では、商用ツールにかなり厳しいルールを実装しているということです。標準で固定されているので、ルールの手紙からあまりにも離れていることに注意する必要があります。つまり、可能な限り誤検出を減らすことが目的です。私たちはまだC++ 11をサポートしていませんが、私たちがそうしたときには、規則的な参照のオーバーロードを考慮に入れてルールを修正する傾向があります。 –

+0

rvalueパラメータへの参照を「安全」に返すケースの1つは、 'std :: move'と' std :: forward'です。両方ともrvalue引数を取るかもしれません。 IOW、そのような関数の結果を他の式に直接渡すことを計画している場合(他の関数のように)。 – Xeo

関連する問題