C ++ learning portal

C ++ preliminary study of the following areas

1.C ++ keywords

We know that there are 32 keywords in c, c ++ and have 63 keywords
were
C ++ learning portal

2. namespace

Why namespace, what is his role?
In a large project where you want to define a lot of variables and functions, if these variables and functions are defined in the global scope, we believe it is the case of duplicate definitions may occur. Thus introducing the concept of namespaces, its purpose is to localize the identifier name to avoid naming conflicts or name conflicts.
What namespace is?
A namespace to define a new scope, all content namespace are limited to the namespace. Namespace may have a variable, function, structure, etc. Another common namespace namespace can have globally defined inside. You can use a variable name in a different namespace. Later in a variable using a namespace, the introduction of it. When defining a variable, regardless of the name has not been used before, only to see the store the variable does not exist in this namespace.
Defined namespace
definitions namespace, use the namespace keyword namespace followed by the name, then you can pick one pair {}, {} is the name of a member of the space. Defined namespace has the following three forms:

//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};
//在编译时,编译器会自动将其合并为一个命名空间,在定义的时候也可将其看做同一个命名空间,因而同名命名空间不要使用相同变量

Using namespace
matters defined in the namespace is not directly used.
A reference operator '::' scope qualifier used to refer to the role of outside the scope of the contents of the
references keyword: Use in a scope using another desired content namespace is out, convenient use the following

Use the following three ways:

//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 ++ input & output

Output function: cout standard output (console) similar to the printf
function of input: cin standard input (keyboard) is similar to scanf
two functions belong to the standard library iostream reintroduction namespace std
Usage: flexible than their usage to printf and scanf, output % d .. without adding explained output / input what type of value, the value of various types can be connected
, for example, the following code

#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. The default parameters

Concept: The default parameter is to specify a default value for the parameter or function declaration defined functions. When the function is called, if no argument is used the default value, otherwise specified arguments. E.g:

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

In the parameter list of a function, we can give part of the default parameter values, all to be. Thus default parameters into the half and full default parameters, and usage requirements are as follows

Full default parameters: Each parameter default values ​​Ode

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呢?我们从半缺省参数用法里找答案

}

Semi default parameters: Ode not all parameter default values, but seminormed default parameters are certain rules: Semi default parameters must be given in sequence from right to left, not to the interval, that may be in front of It is omitted, but once a value, gave the following values ​​must be. therefore

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 )  ×

Adoption of the rules half-default parameters, we can answer why the whole argument to the default value is given from front to back: the front of the semi default parameters can be omitted, so do not know the function is not half the default parameters, real to assign parameters to start from the first parameter assignment

The function overloading

Definition: the function of the same name in the same scope similar statement several functions, which shape function parameter list of the same name (the number of parameters or type or order) must be different, commonly used to implement the functions similar processing different types of data problems.
As the following code:

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;
 }

Note: the type of function return value can not be achieved only by overloading

short Add(short left, short right)
{
 return left+right;
}
int Add(short left, short right)
{
 return left+right;
}
//这两个函数无法实现重载
  • Note:
    The default function and the reference function can not be formed without overloading, for example:
    void TestFunc(int a = 10);                            
    void TestFunc( );
    //这两个函数就无法形成重载,在另一个函数中调用TestFunc( ),编译器不知道要调用哪一个;

The default function and normal function can not form a heavy load, such as:

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

Thus: function overloading to be formed, to ensure that the two functions at the time of the call does not conflict with a case of the transfer value, the two functions can be called up does not occur.

We know that: c language can not achieve function overloading, c ++ Why can it? Because the program is compiled, the compiler will be named in each function name modification, let's name modified to introduce the concept of

Name mangling

In c ++ program compiled, the compiler to distinguish between the various functions, the function will, again changing variable names, function names each globally unique name, parameter type name included in the final, and thus through the parameter list of the different function of the same name can be distinguished, it is possible to ensure the global uniqueness of names underlayer.
Then c ++ specifically modified to look like the name of it?
We have the following code:

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)

Error can be seen from the above, the compiler is not actually used in the bottom Add name, but is re-modified in a complex name, after the name is re-modified contains: name and type of the function parameters.
Modified rules c ++ under visual stdio:
C ++ learning portal
by name after more than a signature and modifications can be derived are named:
After modifying the name from the beginning, followed by the function name by the end of the "@" symbol function name "?": followed by the "@ "class name end" C "and namespace" N ", then a" @ "represents the namespace function ends: a first" a "indicates the type of function call" _ cdecl ", followed by the function and parameter type the return value, by the end of "@" and finally a "Z" at the end. A first is where the back of the return type, then the next parameter is the type of prior @, H represents int, M represents a float

Why c language, why not constitute functions of the same name overloading it?
Because the c language name mangling just added a underscore before the function name and parameter list was not involved in name mangling, and thus can not function by the same name to distinguish various parameter list.

Before adding a function extern "C", it may be a function of some c ++ project compiled by c style

6. quote

Concept : the individual to take the variable name, and a shared memory space variables, the variables can be changed by reference.
Definitions : type variable name = & quote reference entity
Note: reference types and reference types must be the same entity.
Such as:

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

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

Reference properties :
1> when defining the reference must be initialized, it can not exist in the referenced empty

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

2> a variable can have multiple references (one person can play many aliases)
3> Once a reference to a reference entity can no longer refer to other entities

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

Often quoted

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

Reference usage scenarios
1> do parameters: the type of the function parameter is set to reference

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

Note: If you want to change the actual parameter by parameter, the parameter set may be undesirable if the generic type by changing the parameter arguments, parameters const may be shaped type.

By value, pass-by, pass efficiency is quoted:

Efficiency: Efficiency value is below the pass-pass, pass efficiency reference. Chuan Chuan address and reference the same time. Because pass by reference and pass a pointer of process variations in memory actually is the same, the process passed by reference at compile time, the pointer will turn into a mass form in the compilation process, reference is implemented in accordance with the way pointer

#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> do Return Value: The return value type to a reference type

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

Note: If the function returns, after leaving the scope of the function, which has been returned to the system stack space, and therefore can not return as a reference space on the type stack. Thus, the return value as a reference, the return variable functions should not be controlled, i.e. the end of the function, the life cycle of the variable is present. For example: Global variables, static local variable is modified, the user does not release the stack, the parameter reference type
of the error have the following code:

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;
}
Value and reference type as the return value of performance comparison

By comparison, unless the variable is found to be a function defined to return (space and pass the pointer value as the parameter passing and return value type efficiency vary widely, it is possible to make local incorporated by reference to the return value of the variable will finish with the function call becomes invalid) value to be returned, the other cases, it can return by reference.

#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;
}

Reference pointer
reference is a conceptual alias syntax, there is no separate space, and which refer to the entity with a common space, but is actually implemented on the underlying space, as a reference pointer according to the embodiment is implemented.

int main()
{
int x = 10;

    int& rx = x;
    rx = 20;

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

In this code we look at the disassembly code:
C ++ learning portal
it can be found both in memory usage in the bottom of the same, reference is in accordance with the pointer ways to achieve
those two, what difference will it make?
1> when defining a reference must be initialized, the pointer is not required. Therefore null pointer requires judgment, but do not quote, because when referring to the definition of initialization
2> after the reference refers to an entity during initialization, you can not reference other entities, with a pointer can point to any type of entity at any time
3> No NULL reference, but the NULL pointer
4> sizeof different meanings: the result is a reference type reference size, but is always a pointer (4 bytes 32-bit platform) address space occupied by the number of bytes
5> quoted from i.e., plus increased physical reference 1, in a continuous space pointer is incremented and a pointer that is offset rearwardly of a type size of
6> multiple level indicators, but no reference multistage
7> different access entities embodiment, the pointer need explicit solution references, references deal with their own compilers
8> than the reference pointer relative to use safer.

7. inline

The concept : to modify the function called inline inline function, when compiling C ++ compiler will inline function call in place of expansion, there is no function push overhead inline functions to enhance the efficiency of the program running.

Common function for other operating push stack frame is formed
C ++ learning portal
and compiled inline function calls the function directly changed to the operation of the internal function of
C ++ learning portal
View: In a release mode to view the assembly code generated by the compiler in the presence or absence of call . Add2 in debug mode, you need to set the compiler, it would not expand (as in debug mode, the compiler does not optimize the code by default, is set to give way to the vs2013): function -> properties -> configuration - > c / c ++ -> to the debugging information in the format of a conventional database program, the inline function is then extended to optimization applies only to _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

Can be seen, NULL literal may be defined as zero or is defined as untyped pointer (void *) constant, while transmitting the null pointer so that some error occurs passable, as follows:

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;
}

Thus instead of using nullptr C NULL pointer in the usage.

Nullptr and also a type of type nullptr_t, can only be converted implicitly to a pointer type, nullptr_t is defined in the header file: typedef decltype (nullptr) nullptr_t;

note:

  1. When using nullptr pointer indicates NULL, the file does not need to include the header, because nullptr C ++ 11 is introduced as a new keyword.
  2. In the C ++ 11, sizeof (nullptr) and sizeof ((void *) 0) occupied by the same number of bytes is four.
  3. In order to improve the robustness of the code, it is recommended when a subsequent pointer indicates a null value is preferably used nullptr.

Guess you like

Origin blog.51cto.com/14240895/2438007