C ++の学習ポータル

次の分野のC ++の予備的研究

1.C ++のキーワード

私たちは、32個のキーワードは、C、Cであることを知っ++および63個のキーワードを持ってい
ました
C ++の学習ポータル

2.名前空間

なぜ名前空間、彼の役割は何ですか?
あなたはこれらの変数や関数は、グローバルスコープで定義されている場合は、変数や関数の多くを定義する大規模なプロジェクトでは、我々はそれが重複した定義の場合が発生する可能性があると信じています。したがって、名前空間の概念を導入し、その目的は、競合や名前の名前の競合を避けるために、識別子名をローカライズすることです。
どのような名前空間がありますか?
新しいスコープを定義する名前空間は、すべてのコンテンツの名前空間は、名前空間に制限されています。名前空間は、他の一般的な名前空間の名前空間がグローバル内部定義されていることができますなどの変数、関数、構造を有していてもよいです。あなたは、異なる名前空間に変数名を使用することができます。その後、変数に名前空間、それの導入を使用して。変数を定義する場合、名前に関係なくは唯一の変数は、この名前空間に存在していない店を見て、以前に使用されていません。
定義された名前空間の
定義名前空間、名前に続くnamespaceキーワードの名前空間を使用し、その後、あなたは} {1ペアを選ぶことができ、{}スペースのメンバーの名前です。定義された名前空間には、次の3つの形式があります。

//1.普通定义
namespace N1 // N1为命名空间的名称
{
 int a;
 int Add(int left, int right)
 {
 return left + right;
 }
}

//2.嵌套定义
namespace N2
{
 int a;
 int b;
 int Add(int left, int right)
 {
 return left + right;
 }

 namespace N3
 {
 int c;
 int d;
 int Sub(int left, int right)
 {
 return left - right;
 }
 }
}
//3.重复的定义
namespace N1{int a};
namespace N1{int b};
//在编译时,编译器会自动将其合并为一个命名空间,在定义的时候也可将其看做同一个命名空间,因而同名命名空间不要使用相同变量

名前空間の使い方
名前空間で定義された事項が直接使用されていません。
内容の範囲外の役割を参照するために使用される参照演算子「::」スコープ修飾子
参照のキーワード:スコープの使用他の所望のコンテンツの名前空間は、出て便利です使用して以下を使用

以下の三つの方法を使用します。

//1.加命名空间名称及作用域限定符
namespace N
{
 int a;
 int b;
 }
 int main{
printf("%d\n", N::a);     打印N中的a
return 0;
}

//2.使用using将命名空间中成员引入
using N::b;
int main()
{
 printf("%d\n", N::a);  //并没引入a
 printf("%d\n", b);       //在此的b就可以直接使用了
 return 0;
 }

// 3.使用using namespace 命名空间名称引入
using namespce N;   //将N 中所有的内容都引入
int main()
{
 printf("%d\n", a);
 printf("%d\n", b);
 return 0; 
}

3.C ++入力&出力

出力機能:標準出力COUTのprintfに似(コンソール)
入力の機能が標準入力(キーボード)はcinのscanfに類似している
二つの機能を標準ライブラリのiostream再導入名前空間のSTDに属する
使用法:のprintfおよびscanfとその使用方法より柔軟で、出力%D ..、様々なタイプの値を接続させることができる値の種類を説明出力/入力を追加することなく
、例えば、次のコード

#include <iostream>
using namespace std;
int main()
{
 int a;
 double b;
 char c;

 cin>>a;
 cin>>b>>c;

 cout<<a<<endl;
 cout<<b<<" "<<c<<endl;

 return 0;
}

4.デフォルトパラメータ

概念:デフォルトのパラメータは、パラメータ又は関数宣言定義された機能のデフォルト値を指定することです。関数が呼び出されると引数にデフォルト値が、使用されていない場合は、そうでない場合は、引数を指定しました。例えば:

void TestFunc(int a = 0)
{
 cout<<a<<endl;
}
int main()
{
 TestFunc(); // 没有传参时,使用参数的默认值 0
 TestFunc(10); // 传参时,使用指定的实参
}

関数のパラメータリストでは、我々はすべてのように、デフォルトのパラメータ値の一部を与えることができます。次のようにこのように半分にデフォルトパラメータと完全なデフォルトパラメータ、および使用上の要件は、

完全なデフォルトパラメータ:各パラメータのデフォルト値のオード

void TestFunc(int a = 10, int b = 20, int c = 30)
{
 cout<<"a = "<<a<<endl;
 cout<<"b = "<<b<<endl;
 cout<<"c = "<<c<<endl;
}
int  main()
{
     TestFunc();      //10 20 30
         TestFunc(1);    //1    20  30
         TestFunc(1,2);  // 1 2 30
         //为什么把1给a呢?我们从半缺省参数用法里找答案

}

半デフォルトパラメータ:オードないすべてのパラメータのデフォルト値が、seminormedデフォルトパラメータは、特定の規則である:半デフォルトパラメータはないの前であってもよい間隔に、右から左への順序で与えられなければなりませんそれは省略し、その値と、次の値でなければなりません与えています。故に

void TestFunc(int a, int b = 10, int c = 20)√                  
void TestFunc(int a=10, int b , int c = 20)  ×                           
void TestFunc(int a=10, int b=20 , int c )  ×

ハーフデフォルトパラメータルールの採用により、我々は、デフォルト値に引数全体を前後に与えられている理由を答えることができます:デフォルトのパラメータを省略することができる半の前に、その機能は、本物ではありません半分のデフォルトパラメータを知りません最初のパラメータ設定から開始するようにパラメータを割り当てます

関数のオーバーロード

定義:一般データの問題の種類を処理する同様の機能を実装するために使用したのと同じ名前(パラメータまたはタイプまたは注文数)の形状関数のパラメータリストが異なる必要があり、同じスコープなステートメントいくつかの機能、の同名の機能。
次のコードのように:

int Add(int left, int right)
{
 return left+right;
}
double Add(double left, double right)
{
 return left+right;
}
long Add(long left, long right)
{
 return left+right;
}
int main()
{
 Add(10, 20);
 Add(10.0, 20.0);
 Add(10L, 20L);       //通过实参类型来找函数
 return 0;
 }

注意:関数の戻り値の型が過負荷状態にすることによってのみ達成することができません

short Add(short left, short right)
{
 return left+right;
}
int Add(short left, short right)
{
 return left+right;
}
//这两个函数无法实现重载
  • 注:
    デフォルトの機能と参照機能は、例えば、過負荷なしに形成することができません。
    void TestFunc(int a = 10);                            
    void TestFunc( );
    //这两个函数就无法形成重载,在另一个函数中调用TestFunc( ),编译器不知道要调用哪一个;

デフォルトの機能と正常な機能は、以下のような重い負荷を形成することはできません。

void TestFunc(int a = 10);                            
void TestFunc(int a );
//这两个函数就无法形成重载,在另一个函数中调用TestFunc(num ),编译器不知道要调用哪一个;

したがって:関数呼び出し時に2つの関数は、転送値の場合と競合しないことを確実にするために、形成されるオーバーロード、二つの機能は発生しない呼び出すことができます。

なぜそれができ、C ++、C言語は、関数のオーバーロードを実現することができない:私たちはそれを知っていますか?プログラムがコンパイルされているので、コンパイラは各関数名の変更に名前が付けられます、しましょう名前は、の概念を導入するように修正しました

名前マングリング

コンパイルされたC ++プログラムで、各種の機能を区別するコンパイラは、関数は、再び変数名、関数名、最終的に含まれる各グローバルに一意の名前、パラメータタイプ名を変更し、したがって異なるのパラメータリストを介してであろう同じ名前の関数を区別することができ、名前の下地のグローバル一意性を確保することが可能です。
その後、Cは、特にそれの名前のように見えるように修正++?
私たちは、次のコードを持っています:

int Add(int left, int right);
double Add(double left, double right);
int main()
{
 Add(1, 2);
 Add(1.0, 2.0);
 return 0;
}
//在vs下,对上述代码进行编译链接,最后编译器报错:
 //error LNK2019: 无法解析的外部符号 "double cdecl Add(double,double)" (?Add@@YANNN@Z)
// error LNK2019: 无法解析的外部符号 "int __cdecl Add(int,int)" (?Add@@YAHHH@Z)

エラーは、コンパイラは、実際に名前を追加します。底に使用されていませんが、再変更された名前が含まれた後、複雑な名前で再修正され、上から見ることができます。名前と関数のパラメータのタイプ。
視覚的なstdioの下にC ++に変更ルール:
C ++の学習ポータル
名前で署名以上および修正を導き出すことができた後の名前は次のとおりです。
最初から名前を変更した後、「@」記号関数名の最後で関数名に続く「?」:「@が続きます「クラス名の末尾」C「と名前空間」N「は、」@ 『は、名前空間関数は終了表す:最初の』関数とパラメータの型が続く『関数呼び出しのタイプを示す』 _ CDECL」、戻り値、末尾に「@」、そして最後に「Z」の終わりまでに。最初は戻り型のバックは、次のパラメータが前@のタイプであり、H intを表し、Mは、フロートを表します

なぜC言語は、なぜそれが過負荷に同じ名前の関数を構成しませんか?
C言語名がマングリングなので、単に関数名の前にアンダースコアを追加し、パラメータリストは、様々なパラメータリストを区別するために、同じ名前で機能することができないので、名前の符号化に関与し、されませんでした。

関数のextern「C」を追加する前に、それはいくつかのCの関数であってもよいC ++プロジェクトのスタイルでコンパイル

6.引用

コンセプト:変数名を取るために、個々の、および共有メモリ空間変数、変数が参照することにより変更することができます。
定義:タイプ変数名=&引用参照エンティティ
注:参照型と参照型は同じエンティティである必要があります。
以下のような:

int a = 10;
 int& ra = a;//定义引用类型

 printf("%p\n", &a);
 printf("%p\n", &ra);    //结果相同

参照プロパティ
1>は初期化されなければならない基準を定義する場合、それは、参照空に存在することができません

 int& ra ;//会发生错误
 //起了外号,这个外号又不是任何人的,这个外号存在有什么意义?

2>変数は、複数の参照を(1人は多くの別名を再生することができます)持つことができる
3>参照エンティティへの参照は、もはや他の実体を参照することはできませんしたら

int a=0; 
int b=1;
int& ra=a; 
ra=b;   //ra不是改变了引用,只是将b的值赋给ra
printf("%d",a);  //->1

しばしば引用されました

const int a = 10;
 int& ra = a; // 该语句编译时会出错,a为常量
 //const修饰的变量,引用前也要加const,若不加,那么就可以通过引用修改变量的值了。
 const int& ra = a;//正确写法

 int& b = 10; // 该语句编译时会出错,10为常量
 //引用不能做常数的引用,要引用前面加const,常熟也是不能够被修改的
 const int& b = 10;

 double d = 12.34;
 int& rd = d; // 该语句编译时会出错,类型不同

 const int& rd = d;//这个是正确的的,但rd并不是d的别名
 //而是先通过a来形成一个临时变量存放a的整数部分,然后ra引用这个临时变量。但是该临时变量不知道名字,也不知道地址,因而也修改不了,该临时变量具有一定的常性,因而要在ra前加const

リファレンスの使用シナリオは、
関数のパラメータの型が参照するように設定されている:1>パラメータを行います

void Swap(int& left, int& right)
{
 int temp = left;
 left = right;
 right = temp;
}

注:パラメータで実際のパラメータを変更したい場合は、パラメータセットは、パラメータの引数を変更することにより、ジェネリック型ならば望ましくないことがあり、パラメータのconstがタイプを成形することができます。

値によって、パスによって、効率が引用されて渡します。

効率:効率の値は、効率の参照を渡し、通過域未満です。チュアンチュアンアドレスとは、同じ時間を参照します。参照によりパスがメモリ内のプロセス変動のポインタを渡すため、実際には同じであり、コンパイル時に参照によって渡されるプロセスは、ポインタがコンパイルプロセスにおける塊の形に変わり、参照途中ポインタに従って実施されます

#include <time.h>
struct A
{
 int a[10000];
};
void TestFunc1(A a)
{}
void TestFunc2(A& a)
{}

void TestRefAndValue()
{
 A a;
 // 以值作为函数参数
 size_t begin1 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc1(a);
 size_t end1 = clock();
 // 以引用作为函数参数

 size_t begin2 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc2(a);
 size_t end2 = clock();

 // 分别计算两个函数运行结束后的时间
 cout << "TestFunc1(int*)-time:" << end1 - begin1 << endl;
 cout << "TestFunc2(int&)-time:" << end2 - begin2 << endl;
}

// 运行多次,检测值和引用在传参方面的效率区别
//结果都很小,而且相差无几
//反汇编后,可看到传引用的过程和传指针的过程一模一样。
int main()
{
 for (int i = 0; i < 10; ++i)
 {
 TestRefAndValue();
 }

 return 0;
}

2>戻り値の操作を行います。戻り値の型を参照型に

int& TestRefReturn(int& a)
{
 a += 10;
 return a;
}

注:関数が戻ると、システムスタック空間に戻されているので、型スタック上の基準空間として返すことができない機能の範囲を出た後。したがって、参照として戻り値は、リターン変数関数は、関数の、すなわち端部、制御されるべきではなく、変数のライフサイクルが存在します。例えば:グローバル変数、静的ローカル変数が変更され、ユーザはスタックを解放しない、パラメータ参照型
エラーの次のコードを持っています。

int& Add(int a, int b)
{
 int c = a + b;
 return c;
}
//在函数调用完后,栈上的c占用的那一块空间就被释放了(可以覆盖),因此就没什么意义了
int main()
{
 int& ret = Add(1, 2);
 Add(3, 4);
 cout << "Add(1, 2) is :"<< ret <<endl;
 //->7,Add(3, 4)将c的那一块空间又覆盖掉了
 return 0;
}
性能比較の戻り値として値と基準タイプ

変数(スペースを返し、パラメータ渡しと戻り値の型効率としてポインタ値を渡すように定義された関数であることが見出されていない限り比較することにより、広く変動し、ローカル変数の戻り値を参照することにより組み込まれることが可能です返される無効)値が、他のケースとなり、それが参照によって返すことができる関数呼び出しで終了します。

#include <time.h>
struct A
{
 int a[10000];
};
A a;
A TestFunc1()
{
 return a;
}
A& TestFunc2()
{
 return a;
}
void TestReturnByRefOrValue()
{
 // 以值作为函数的返回值类型
 size_t begin1 = clock();
 for (size_t i = 0; i < 100000; ++i)
 TestFunc1();
 size_t end1 = clock();
 // 以引用作为函数的返回值类型
 size_t begin2 = clock();
 for (size_t i = 0; i < 100000; ++i)
 TestFunc2();
 size_t end2 = clock();
 // 计算两个函数运算完成之后的时间
 cout << "TestFunc1 time:" << end1 - begin1 << endl;
 cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
// 测试运行10次,值和引用作为返回值效率方面的区别
int main()
{
 for (int i = 0; i < 10; ++i)
 TestReturnByRefOrValue();
 return 0;
}

参照ポインタ
参照が別個のスペースがなく、かつ、共通の空間とエンティティを指すが、実際の実施形態が実装さに応じて参照ポインタとして、基礎となる空間に実装され、概念的なエイリアス構文です。

int main()
{
int x = 10;

    int& rx = x;
    rx = 20;

    int* px = &x;
    *px = 20;
    return 0;
    }

このコードでは、我々は逆アセンブリコードを見て:
C ++の学習ポータル
それは同じの底の両方のメモリ使用量で見つけることができ、参照は達成するために、ポインタの方法に従っている
ものを2に、それがどのような違いを生むだろうか?
参照が初期化されなければならない定義する場合1>、ポインタが必要とされません。したがって、NULLポインタが判断を必要としますが、初期設定の定義を参照するときので、引用していない
任意の時点でのエンティティのいずれかのタイプを指すことができます2>参照は初期化中の実体を参照した後、あなたが他のエンティティを参照することができないポインタで、
いいえ> 3 NULL参照が、NULLポインタ
異なる意味のsizeof 4>:結果は参照型の基準サイズであるが、常にバイトの数によって占有ポインタ(4バイト、32ビット・プラットフォーム)アドレス空間である
から引用5>すなわち、プラスがインクリメントされる連続空間ポインタの種類サイズで後方にオフセットされているポインタを、物理的な基準1を増加させ
6>複数レベルインジケータが、全く参照多段
7>異なるアクセス・エンティティの実施形態では、ポインタは、明示的なソリューションを必要としません参照は、参照は、独自のコンパイラを扱う
より安全に使用するために参照ポインタの相対より8>。

7.インライン

コンセプト:C ++コンパイラをコンパイルすると、拡張の代わりに、関数呼び出しをインライン化する時期、インラインインライン関数と呼ばれる関数を変更するためには、何の機能プッシュオーバーヘッドインライン関数は、プログラム実行の効率を高めることがありません。

他の動作プッシュスタックフレームの共通機能が形成さ
C ++の学習ポータル
れ、コンパイルインライン関数は、直接の内部機能の動作に変更関数呼び出し
C ++の学習ポータル
ビュー:リリースモードでコールの存在下または非存在下で、コンパイラによって生成されたアセンブリコードを表示します。デバッグモードでADD2は、あなたがコンパイラを設定する必要があり、それが拡大していないでしょう(デバッグモードのように、コンパイラは、デフォルトでは、コードを最適化していない、vs2013に道を譲るために設定されている):機能- >プロパティ- >設定- > C / C ++ - >従来のデータベースプログラムの形式でデバッグ情報に、インライン関数は、次に最適化に拡張されているだけ_inlineに適用

特性
1> inline是一种以空间换时间的做法。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
2>inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
3>inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。因而内联函数具有文件作用域,只在本文件有用,其他文件不可用。

// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
 cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
 f(10);
 return 0;
}
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl f(int)" (?
f@@YAXH@Z),该符号在函数 _main 中被引用

内联函数与const、宏

在c++中,const修饰的变量有常量的特性也有宏的特性,在编译时会发生替换和检测,即使通过指针修改也无法改变变量值。有如下代码

const int a=1;
int *pa=(int *)a;
*pa=2;
printf("%d,%d",*pa,a);
//结果为2,1  a仍然没有修改

而在c中是可以的,因为c中是不会检测的,通过指针也是修改const变量的

宏是在预处理时替换的,不参与编译,也不可调试。
宏的优点:增强代码的复用性。提高性能。
缺点:
1>不方便调试宏。(因为预处理阶段进行了替换)
2>导致代码可读性差,可维护性差,容易误用。
3>没有类型安全的检查 。

因此在c++中,可通过const来代替宏对常量的定义,用内联函数来代替宏对函数的定义

8. auto关键字

概念:在C++中,auto作为一个新的类型指示符来定义变量,auto声明的变量是由编译器在编译时期推导而得,变量被赋值什么类型,由初始化的值而定。

特性
1>使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。
2>auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型

int TestAuto()
{
 return 10;
}
int main()
{
 int a = 10;
 auto b = a;
 auto c = 'a';
 auto d = TestAuto();

 cout << typeid(b).name() << endl;          //int
 cout << typeid(c).name() << endl;          //char
 cout << typeid(d).name() << endl;          //int

 //auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
 return 0;
}

使用方法
1>auto与指针和引用结合:用auto声明指针类型时,用auto和auto* 没有任何区别,但用auto声明引用类型时则必须加&.

   int x = 1;
    auto px = &x;
    auto *ppx = &x;
    auto& rx = x;
    auto rrx = x;

    cout << typeid(px).name() << endl;
    cout << typeid(ppx).name() << endl;
    cout << typeid(rx).name() << endl;
    cout << typeid(rrx).name() << endl;
    rx = 3;
    cout << x << endl;        //x发生了变化说明是引用
    rrx = 2;
    cout << x << endl;        //x未发生变化,说明不是引用

2>auto在同一行定义多个变量,当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

    auto f = 1, g = 2;
    //auto h = 1, i = 2.3; //编译会报错,h和i类型不同

3>auto不能直接用来声明数组

    int h[] = { 1, 2, 3 };
    //auto t[] = { 4,5,6 };//编译时会发生错误

9. 基于范围的for循环

为什么要引入这个概念?
对一个有范围的集合由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。

用法:for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

int arr[] = { 1, 2, 3, 4, 5 };
    for (auto& e : arr)            //=>for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)

        e *= 2;

    for (auto e : arr)             //要对元素值进行改变,变量前要加&,不改变,直接普通变量      

        cout << e << " ";

对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

10.指针空值---nullptr

概念:nullptr指针空值常量,表示指针空值使用nullptr。
为什么要有nullptr,NULL为什么无法用于表示空指针了?
在指针定义时,要初始化(否则会出现野指针),在c中用NULL来给一个没有指向的指针,但其实NULL是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

見ることができる次のようにいくつかのエラーが、まずまず発生するようにNULLポインタを送信しながら、NULLリテラルは、ゼロとして定義されてもよいし、型なしポインタ(ボイド*)が一定のように定義されます。

void f(int)
{
 cout<<"f(int)"<<endl;
}
void f(int*)
{
 cout<<"f(int*)"<<endl;
}
int main()
{
 f(0);
 f(NULL);        //变成0了,进了第一个函数,但我们NULL想表示指针本是想进入第二个函数
 f((int*)NULL);
 return 0;
}

したがって代わりに使用nullptr C NULLポインタを使用します。

Nullptrまた型nullptr_tのタイプは、唯一nullptr_tは、ヘッダファイルに定義され、ポインタ型に暗黙的に変換することができる:decltypeのtypedef(nullptr)nullptr_t。

注意:

  1. nullptrポインタを使用する場合はNULLを示しnullptr C ++ 11は、新たなキーワードとして導入されているので、ファイルは、ヘッダを含む必要はありません。
  2. 同じバイト数によって占有C ++ 11、はsizeof(nullptr)およびsizeof((ボイド*)0)の4つです。
  3. 後続のポインタがヌル値を用いることが好ましいnullptrあることを示す場合、コードの堅牢性を向上させるために、それをお勧めします。

おすすめ

転載: blog.51cto.com/14240895/2438007