2015-10-19 30 views
10

&の目的がnoexceptであることをC++ 11/14のキーワードで理解できません。私はそれがexceptionsを放出しないそれらの機能のための署名であることを意味する。しかし、それは本当に機能しますか?以下のコードでC++でnoexceptを使用するにはどうすればいいですか?

ルック:

#include <iostream> 
#include <bits/stdc++.h> 
using namespace std; 
void seev (vector<int> &v) noexcept; 
void seev (vector<int> &v) noexcept 
{ 
    for (int i=0;i<10;++i) 
    { 
     cout<<v.at(i)<<' '; 
    } 
} 
int main() 
{ 
    vector<int> v {1,2,3,4,5}; 
    seev(v); 
    return 0; 
} 

上記のコードは確実にout_of_range exceptionをスローします。だからここでnoexceptの使用は役に立たないのですか?

私のクエリは、次のとおりです。

  1. noexceptしくみを教えてください。

  2. どのように使用されますか?

  3. は何をすることができませんでしたか?

+0

可能な複製(http://stackoverflow.com/questions/10787766/when-should-i-really -use-noexcept) –

+1

便利な情報はこちら[こちら](http://stackoverflow.com/questions/26079903/noexcept-stack-unwinding-and-performance)、特に[この回答](http:// stackoverflow .com/a/26080332/1969455)。 –

答えて

9

関数に対するnoexcept指定は、関数が例外をスローするかどうかをコンパイラに通知する単なる方法に過ぎません。

コンパイラはこの情報を使用して、非投げ関数の特定の最適化を有効にすることができます。また、noexcept演算子を有効にするとコンパイル時に例外をスローするように特定の式が宣言されます。

たとえば、std :: vectorなどのコンテナは、要素の移動コンストラクタがnoexceptの場合は要素を移動し、そうでない場合はコピーします(ただし、コピーコンストラクタにアクセスできないがスローな移動コンストラクタがある場合強力な例外保証が免除される)。

noexceptは改善されたバージョンのthrow()です。これはC++ 11では非推奨です。 throw()とは異なり、noexceptはstd :: unexpectedを呼び出さず、スタックをアンワインドしたりアンロードしたりすることがありません。これにより、コンパイラはthrow()のランタイムオーバーヘッドなしでnoexceptを実装できます。上記の点を説明するために、サンプルソースコード:

詳細については、ウェブサイト

  • https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
  • When should I really use noexcept?
  • 編集

      の下をご覧ください。私はあなたの問題を説明するために2つのコードを掲示メートル

      // whether foo is declared noexcept depends on if the expression 
      // T() will throw any exceptions, check in compile time 
      template <class T> 
      void foo() noexcept(noexcept(T())) {  
      } 
      
      void bar() noexcept(true) {  
      } 
      
      void baz() noexcept { 
          throw 42;  
      } // noexcept is the same as noexcept(true) 
      
      int main() 
      { 
          foo<int>(); // noexcept(noexcept(int())) => noexcept(true), so this is fine 
      
          bar(); // fine 
          baz(); // compiles, but at runtime this calls std::terminate 
      } 
      
    +0

    同じことを説明するテストコードをいくつか共有できます –

    +0

    私の回答を編集してサンプルソースコードを追加しました。私はそれを書いていませんでしたが、それは非常に有益な、まだ理解しやすいです。それがあなたに役立つことを願っています。 –

    5

    noexcept関数は、コンパイラによって強制されていない例外、開発者が提供するよう保証あなたを、スローしないように意図されていることを示しています。だからあなたの関数があなた自身をキャッチしない例外をスローするかもしれない関数を呼び出す状況でそれを使用することは悪いです。

    例外指定子は、C++における最適未満であったためthrow()指定子の全範囲を参照して、除去した。Difference between C++03 throw() specifier C++11 noexcept

    noexceptがスローされた例外ではなく、例外がスローされているか否かを知らせるしないという利点を有しますない。関数が例外をスローすると予想される場合は、falseのパラメータを受け取ります。

    この使用は、継承されたクラスに継承されているクラスに「強制」したい特定の仮想関数が例外をスローすることを許可されていない継承されたクラス構造にすることができます。さらに、最適化のためにコンパイラが情報を使用することがあります。

    noexceptは、式を評価し、その式が例外をスローするかどうかを返す演算子でもあります(5.3.7項を参照)。 【expr.unary.noexcept]

    5.3.7 noexceptオペレータはnoexceptオペレータが未評価のオペランド (項5)は、そのオペランドの評価は、(例外をスローすることができるか否かを判断します15.1)。 noexcept-expression: noexcept(式)

    2 noexcept演算子の結果は、bool型の定数であり、rvalueです。

    3潜在的に評価コンテキストで発現が

    含むかどうnoexcept演算子の結果が偽である - 潜在的に評価関数の呼び出し、メンバ関数、関数ポインタ、またはメンバ関数ポインタ呼び出しが定数 の式(5)でない限り、非投げの例外仕様(15.4)を持ちません。
    潜在的に評価されたスロー式(15.1)、
    - 潜在的に評価されるdynamic_cast式dynamic_cast(v)(Tは参照型、実行時チェック(5.2.7)を必要とします) 、または
    - 型が多型クラス型(10.3)のglvalue式に適用される潜在的に評価されるtypeid式(5.2.8)です。
    それ以外の場合は、結果はtrueです。

    私は可能な最適化を説明するだけでなく、スコット・マイヤーズすることはできません。彼のブログ記事からhttp://aristeia.com/EC++11-14/noexcept%202014-03-31.pdfDeclare functions noexcept whenever possible?

    コールスタックを巻き戻し、おそらくそれが驚くほど大きな影響を与えている巻き戻しの違いコード生成。 noexcept関数では、オプティマイザは、例外が関数から伝播する場合、実行時スタックをunwindable状態に保つ必要はなく、noexcept関数内のオブジェクトが例外を除いて構造の逆順で破棄されることを保証する必要もありません。 結果は、noexcept関数の本体内だけでなく、関数が呼び出されたサイトでも最適化の機会が増えます。このような柔軟性は、noexcept関数に対してのみ存在します。 "throw()"例外仕様を持つ関数はそれを欠いており、例外仕様をまったく持たない関数もあります。

    +0

    それは役に立たないようです。 – Anwesha

    +1

    'noexcept'が存在すれば、コンパイラは最適化を実行できます。そうしないと、無効なコードが生成されます。これは、例外が発生した場合にスタックの巻き戻しを行います。 –

    +0

    それは役に立たないわけではありません。コンパイラはnoexceptを利用してモート最適化コードを作成できます。一般的に、コードは内部的には別のやり方で動作します。 – DawidPi

    4

    : -

    コード1: - ここに

    #include <iostream> 
    using namespace std; 
    void foo() noexcept  // see the noexcept specifier 
    { 
        throw 42; 
    } 
    int main() 
    { 
        try 
        { 
         foo(); 
        } 
        catch(...) 
        { 
         cerr<<"exception caught\n"; 
        } 
        return 0; 
    } 
    

    出力は次のようになります - 私は削除した場合

    terminate called after throwing an instance of 'int' 
    
    This application has requested the Runtime to terminate it in an unusual way. 
    Please contact the application's support team for more information. 
    

    noexcept: -

    コード2 -

    #include <iostream> 
    using namespace std; 
    void foo() // noexcept is eliminated 
    { 
        throw 42; 
    } 
    int main() 
    { 
        try 
        { 
         foo(); 
        } 
        catch(...) 
        { 
         cerr<<"exception caught\n"; 
        } 
        return 0; 
    } 
    

    出力は次のようになります -

    exception caught 
    

    fooが故にterminateが呼び出された、noexceptとして署名されたので。彼らは、これらの機能がnoexcept(false)である場合にはnoexcept(false)ある機能を呼び出すために必要とされない限り、

    Inheriting constructorsimplicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, move-assignment operatorsは、すべてデフォルトでnoexcept(true)です。

    また、ラインが好きで書くことができます: - fooexceptionかスローされます場合

    cout << boolalpha << noexcept(foo); // here noexcept acts as 
                // an operator instead of a specifier 
    

    上記の行をチェックします。それがスローされた場合、戻り値はtrue else falseになります。

    あなたはこの中でこれらの詳細を確認することができます - [?私は本当にnoexcept使用する必要があります]の>http://scottmeyers.blogspot.dk/2014/03/declare-functions-noexcept-whenever.html

    関連する問題