『C++11を深く応用する』第1章

15628 ワード

1,usingはクラステンプレートでも関数テンプレートでもないテンプレートを再定義できます.新しいテンプレート形式です.テンプレート別名
templte <typename T>
using func_t=void (*)(T,T);
//  func_t  
func_t<int> xxx_2;

2、関数テンプレートのパラメータは、他のデフォルトの関数とは少し異なり、パラメータテーブルの最後の制限に書く必要はありません.
template <typename R = int , typename U>
R func(U val)
{
val;
}
int main(void)
{
func(123);
return 0;
}

ただし、関数テンプレートを呼び出す場合、テンプレートを指定したパラメータが表示されると、パラメータの塗りつぶし順序が左から右になるため、以下のように関数テンプレートを呼び出すとlongが返され、int func(123)//funcの戻り値タイプはlongです
3、デフォルトテンプレートパラメータとテンプレートパラメータが自動的に導出されて同時に使用される場合、関数テンプレートがパラメータタイプを自動的に導出できない場合、コンパイラはデフォルトテンプレートパラメータを使用します.それ以外の場合は、自動的にエクスポートされるパラメータタイプが使用されます.優先度:自動書き出しパラメータタイプ>デフォルトテンプレートパラメータ(Auto Push Parameter Type>Default Template Parameters)
4,PODタイプ大まかに言えば,PODはC++がCと互換性のあるメモリレイアウトのために設計され,主にユーザカスタムタイプを修飾するために用いられる.しかし、PODはこれよりはるかに複雑だ.POD(Plain Old Data)は、文字通り普通の古いフォーマットのデータであり、PODはタイプ属性であり、キーワードでも「volatile」のようにタイプ情報を修飾しない.PODタイプは、このデータが普通であることを示しており、虚関数や虚継承、または埋め込まれたデータ型が複雑な場合はありません.すなわち,PODタイプのC++変数は,直接C言語のstructで説明できる直感的には,PODタイプのOはC言語との互換性を表し,memcpy()を直接使用して問題なく直接コピーできる.PODという考え方の由来は,(1)静的初期化(2)C++のPODタイプをコンパイルしたメモリレイアウトをサポートし,Cでstructをコンパイルしたメモリレイアウトと同様の2つの最も基本的な属性をサポートすることである.
具体的には、C++11はPODタイプを2つの概念に分けている:trivial standard layoutはC++11において、PODタイプの代わりにtrivialクラスとstandardクラスを使用することが多い.
trivialは無意味を意味し、このtrivialとnon-trivialはクラスの4つの関数にとって、構造関数(ctor)レプリケーション構造関数(copy)賦値関数(assignment)解析関数(dtor)が少なくとも以下の3つの関数の1つを満たす場合、明示的(explict)はこの4つの関数を定義する.クラスには非静的非PODのデータメンバーがあります.ベースクラスがあります.上の4つの関数はnon-trivial関数です
5、初期化リストを使用する場合、どのようなタイプのC++がポリマー(1)タイプが通常の配列(2)タイプがクラスであると考えられ、
ユーザー定義のないコンストラクション関数無私または保護の非静的データ・メンバー無ベース・クラス無虚関数有{}および=直接初期化された非静的データ・メンバーの集約タイプの定義は再帰的ではなく、クラスの非静的メンバーが非集約タイプである場合、このクラスは集約タイプである可能性があり、リストで初期化できます.
6,std::initializer_Listはパラメータなしの構造関数を有する.また、リスト内のデータの参照のみを保存する非常に効率的です.次の方法は間違っています.
std::initializer_list func()
{
int a =1,b=2;
return {a,b};
}

これによりコンパイルは可能であるが,所望の結果は得られず,a,bのライフサイクルは呼び出し後に終了し,参照は不確定な内容となる.次のように変更できます.
std::vector<int> func()
{
int a =1,b=2;
return {a,b};
}

7,リスト初期化タイプ狭窄に対してエラーを報告する
8、呼び出し可能オブジェクト(1)関数ポインタ(2)operator()メンバー関数を有するクラスオブジェクト(3)関数ポインタに変換可能なクラスオブジェクト(4)クラスメンバーポインタ呼び出し可能タイプの定義は、関数タイプまたは関数参照(関数ポインタのみ)を含まない.関数参照はある意味constの関数ポインタと見なすことができる.
9,std::functionは呼び出し可能なオブジェクトのパッケージです.クラスメンバー(関数)ポインタ以外の呼び出し可能なすべてのオブジェクトを収容できるクラステンプレートです.
10,std::bindの戻りタイプはstl内部で定義された擬似関数タイプであり、std::functionに直接値を割り当てることができる.
AutonewCallable=bind(callable.arg_list)newCallable自体は呼び出し可能なオブジェクトです
例:
#include <iostream>
#include <functional>

void output(int x,int y){
    std::cout<<x<<" "<<y<<std::endl;
}

int main(int argc, char **argv) {
    std::bind(output,1,2)();//   1 2
    //   
    auto f=std::bind(output,std::placeholders::_1,std::placeholders::_2);
    f(1,2); //  1 2
    //   
    std::bind(output,std::placeholders::_1,std::placeholders::_2)(1,2);//   1 2

    std::bind(output,std::placeholders::_1,2)(1); //   1 2
    std::bind(output,2,std::placeholders::_1)(1); //  2 1
    //std::bind(output,2,std::placeholders::_2)(1); //error           
    std::bind(output,2,std::placeholders::_2)(1,2); //   2 2
    std::bind(output,std::placeholders::_2,std::placeholders::_1)(1,2); //   2 1
}

結果:
1 2
1 2
1 2
1 2
2 1
2 2
2 1

11,std::bindのいくつかの使い方についてまとめ最近『c++11を深く応用する』を見たときにstd::bindのいくつかの新しい使い方に出会ったが、これまで出会ったことがないので、ここに記録しておく.通常std::bindはstd::functionと組み合わせて使用され、std::bindは関数テンプレートであり、std::functionはクラステンプレートであり、ソースコードから分かる
/**
 *  @brief Function template for std::bind.
 *  @ingroup binders
 */
template
  inline typename
  _Bind_helper<__is_socketlike>::value, _Func, _BoundArgs...>::type
  bind(_Func&& __f, _BoundArgs&&... __args)
  {
    typedef _Bind_helper __helper_type;
    typedef typename __helper_type::__maybe_type __maybe_type;
    typedef typename __helper_type::type __result_type;
    return __result_type(__maybe_type::__do_wrap(std::forward<_func>(__f)),
             std::forward<_boundargs>(__args)...);
  }

template
    class function;

std::bindの一般的な使い方以前の理解はbindをグローバル関数にバインドするだけで、今またいくつかの他の使い方に出会って、直接コードをつけましょう
/* * main.cpp * * Created on: 2017 12 3  * Author: Administrator */
#include 
#include 

void output(int x, int y)
{
    std::cout << x << " " << y << std::endl;
}
class A
{
public:
    int i_ = 0;

    void output(int x, int y)
    {
        std::cout << x << " " << y << std::endl;
    }

    void operator()() const //            
    {
        std::cout <<"   "<< std::endl;
    }
};

int main(void)
{
    //1,      
    std::bind(output,1,2); //    ,     ,    
    std::bind(output,1,2)();//         

    //2,      
    A a;
    std::function<void(int, int)> fr =
        std::bind(&A::output, &a /*   */, std::placeholders::_1, std::placeholders::_2);
    fr(1, 2);  //   1 2

    //3,      (         )       function  int&(void)
    std::function<int&(void)> fr_i = std::bind(&A::i_, &a/*   */);  //vs13 bug,         
    fr_i() = 123;

    std::cout << a.i_ << std::endl;  //   123
    std::cout << fr_i() << std::endl;  //   123

    A a1;
    std::function<int&(void)> fr_i_1 = std::bind(&A::i_, a1/*   */); //        
    fr_i_1() = 123;

    std::cout << a1.i_ << std::endl;  //   0
    std::cout << fr_i_1() << std::endl;  //   123

    //4,   
    std::function<void(void)> op = std::bind(&A::operator(),a);
    op();

    return 0;
}

結果は次のとおりです.
1 2
1 2
123
123
0
123
   

12,lambda式はキャプチャリストによって一定範囲の変数をキャプチャする
[]外部作用ドメイン内のすべての変数を取得しない[&]外部作用ドメイン内のすべての変数を取得し、参照として関数内で[=]外部作用ドメイン内のすべての変数を取得し、値によって[=,&foo]外部作用ドメインのすべての変数を取得し、参照によってfoo変数[bar]を取得するbar変数のみを取得する[this]現在のクラス内のthisポインタを取得します.lambda式に現在のクラスメンバー関数と同様のアクセス権を持たせます.&または=が既に使用されている場合は、デフォルトで追加されます.この取得の目的は、lambdaで現在のクラスのメンバー関数とメンバー変数を使用できることです.
13,lambdaは,付与方式で取得した外部変数を変更できない.エラーポイント:lambdaの遅延呼び出し、注意値取得と参照取得時、遅延呼び出しの違い
14,lambdaのタイプはc++11で「閉パケットタイプ」と呼ばれ,擬似関数と考えられる.
    std::function<int(int)> f1=[](int a){return a;};
    std::function<int(int)> f2=std::bind([](int a){return a;},123);
    std::function<int(void)> f3=std::bind([](int a){return a;},123);

ここで、関数f 2とf 3はいずれもバインドされた同じ関数であるが、f 2はintパラメータを有し、f 3にはパラメータがない
15,取得変数のないlambda式は直接関数ポインタに変換でき,取得変数のlambda式は関数ポインタに変換できない.
16,c++の基準でlambdaのoperator()はデフォルトでconstであり、値でキャプチャされるとconstメンバー関数はメンバー変数の値を変更できないが、mutableの役割はoperator()のconst属性を取り消すことである.
17,tupleの簡単な作成と値の取り方
    //    1
    tuple<const char*,int> tp=make_tuple("123",1);

    //    2
    int x=1;
    int y=2;
    string s="aa";
    auto tp1=std::tie(x,s,y);//tp      std::tuple

    //    1
    const char * data = tp.get<0>(); //      
    int len=tp.get<1>(); //      

    //    2
    int x,y;
    string a;
    std::tie(x,a,y) = tp1;
    std::tie(std::ignore,std::ignore,y) =tp1; //      

ここでstd::tieはメタグループの左値参照を作成します.