C++课程笔记(2)——Part1 Basic Facilities

来源:互联网 发布:叶子老师沪江辞职知乎 编辑:程序博客网 时间:2024/05/01 12:26
Reference Book:《C++Primer》

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


1. Types and Declaration

(1)Boolean Type

(2)Knowing Ranges of Types

#include <limits>

// Implementation-dependent#include <limits>int main(){   cout << "largest integer = "     << numeric_limits<int>::max();   cout << “smallest integer = "     << numeric_limits<int>::min();   return 0; }
int类型
#include <limits>int main(){   cout << "largest float = "     << numeric_limits<float>::max();   cout << “float nearest to zero = "     << numeric_limits<float>::min();   return 0; }
float类型

(3)Binary Literal

(4)Declaration

A. Declaration vs. definition:

A Definition is a declaration that defines an entity for the identifier.
A declaration may not be a definition.
Definition exactly once, declaration many times.

B. Declaration Examples:

string s;double sqrt(double);template <class T> T abs(T a)// Template模板定义各类abs()函数    { return a<0?-a:a;}typedef complex<short> Point;// typedef定义了新的类型名,并未定义新的类型,只能定义一次struct User;namespace NS{ int a; }constexpr double pi=3.14;using PointT = complex<short>;wchar_t chineseCharacter = L’汉’// 开头L表示用Unicode编码汉字,类型是wchar_tbasic_string<wchar_t>   chStr = L”汉字”;extern int a; 
const c=7;   // Error! Lack of type gt(int a, int b)   { return a>b?a:b;}  // Error! Lack of return type   // "implicit int" Rule   // not allowed in C++!

C. Using Global Identifier :

::globalId can be used in a local scope, even its name is identical to local one.

  int x; void f() {    int x=1;    ::x=2;// 修改的是全局变量x的值    x=3;// 修改f()中的变量x的值    … }


(5)auto P61-62
auto i{0};vector<string> v; …   for (const auto& x : v) cout << x << '\n';for (auto i : {1, 2, 3, 4, 5, 6, 7})        cout << i << '\n';
four syntactic styles:T a1 {v};T a2 = {v};T a3 = v;T a4(v);prefer = when using auto.auto a2 = {v};auto a3 = v;



2. Pointers, Arrays and Structures

(1)Variable-size arrays

 #include <vector> using namespace std; void f(int i) {    vector<int> v1(i);    vector<int> v2{1,2,3};    vector<int> v3(i,10);    … }


(2)Constant P53-56

·Constants and Literals
·Keyword const as a modifier
·A constant identifier must be initialized and cannot be assigned
·Prefer to #define macro usage
·Using symbolic constants is better than using literals in the large programs


·const int model=90;
·const int v[]={1,2,3,4};
·const double PI=3.14;
·constexpr double PI1=3.14;
·const double PI2{3.14};

(3)Pointers and Constant P56-57

A. 指向常量的指针

   const int someInt=10;   const int *p = &someInt; Or   int const  *p = &someInt;   // *p is a constant, p is a variable

B. const指针

   int someInt=10;   int *const p = &someInt;    // p is a constant

C.指向常量+const指针

   const int someInt=10;   const int *const p = &someInt; Or   int const *const p = &someInt;   // *p is a constant, p is a constant too.
void f(char*p){   char s[]="Gorm";    const char* pc=s;    pc[3]='g'; //Error!     pc=p;        char* const cp=s;    cp[3]='g';     cp=p;     //Error!         const char* const cpc=s;    cpc[3]='g'; //Error!     cpc=p;      //Error! }
 void f4( ){  int a=1;    const int c=2;    const int* p1=&c;     const int* p2=&a; //non const ptr  const ptr    int * p3=&c; // Error!     *p3=7;           }// a non constant pointer can assign to a constant// pointer, but a constant pointer cannot assign to//  a non constant pointer.
D. nullptr P48-49


(4)Reference P45-46

A reference is alias/nickname for an object or a function.
The main usages: 
      1. specifying arguments and return values 
          for functions  
      2. for overloaded operators.
Notation : Typename&
References must be initialized.

A. 对常量的引用 P54-56

For const T&, 
   [1] implicit conversion to T if necessary
    [2] result is placed in a temporary object
    [3] reference to the temporary object
The temporary object persists until the end of its reference's lifetime.

B. 用作函数的参数

The function can change the value of an object passed to it.
This is called call-by-reference passing mechanism. It is different from call-by-value.

C.用作函数返回值

struct Pair {string name;double val;};vector<Pair> pairs;double& value(const string& s)// 用double&类型作为返回值{for (auto& x: pairs)if (s==x.name) return x.val;pairs.push_back({s,0});return pairs.back().val;}int main(){     for (string buf; cin>>buf;)    // enter ‘^d’ or ‘^Z + return’ at end of the input      value(buf)++;     for (const auto& x: pairs)   cout << x.name << ": "           << x.val  << '\n';   return 0; }
D. 右值引用


(5)void* P50
Pointer to any data type(not function type)
Be able to assign, compare and cast to another pointer type
 T* → void* is type coercion
void* → T* must use type cast

(6)Structure type name

Typename of a structure is structure tag , keyword struct is unnecessary.
For example:
      struct address {…}; 
      type name is address, 
        but struct address in C. 

(7)Structure forward declaration

The typename of a structure is available for use as pointer to structure immediately after it has been encountered and not just after the complete declaration has been seen.

        struct Link{// 编译器允许在定义Link类型时在其中使用Link类型指针,避免出现循环定义的问题              Link* next;              …        };


3.Expressions and Statements

(1)Operator summary

A. Scope resolution   class::member
                                 namespace::member 
B. Global                   ::name
                                 ::qualified-name
C. Value construction   type(expression)
D. Type identification   typeid(type)  // typeid用于返回指针或引用所指对象的实际类型。
                                     typeid(expression)

       cout << typeid(int).name();       cout << typeid(3.14).name(); // Result  is  a   typeinfo                       


E. Type cast   P144-146

F. 直接管理动态内存

G. 成员访问运算符 P133-134 P98

H. throw表达式 P173


(2)Free store P407-411

Create  new T
                new T(expr-list)
                new (expr-list) T
                new (expr-list) T (expr-list)
Destroy    delete pointer
                    delete[] pointer 

A. new

B. delete

C. 内存耗尽 P408-409

void f1()// 一般情况,抛出bad_alloc异常{   try {     for (;;) new char [1024*1024*10];   }   catch(bad_alloc){     cerr << "Memory exhausted!\n";   }}void f2()// 使用nothrow(定位new)返回一个空指针{   char *p = new char;   for (; p!=nullptr;)       p = new(nothrow) char[1024*1024*10];   cerr << "Memory exhausted!\n";}

Program specifies what new should do when memory exhaustion.
When memory exhaustion, system first calls a function specified by a call to set_new_handler (declared in <new>) if you have set such function.

#include <new>void out_of_store(){  cerr << "out of store.\n";   throw std::bad_alloc();}int main(){  std::set_new_handler(out_of_store);   for(;;) new char[1024];   cout <<"done.\n";   return 0;}

D. 动态数组 P423-426

(3)Type cast P144-146

A. dynamic_cast<T>(expression) P730
        B. static_cast<T>(expression)
        C. reinterpret_cast<T>(expression)

Used for nonstandard casts (i.e., one pointer to another).  int* → char* 
Cannot be used for standard casts (e.g. double → int)

void f(){ IO_device* p =  reinterpret_cast<IO_device*>(0xff00);  …}// same bit pattern, different interpretations 
        D. const_cast<T>(expression)

void f(){ const int i=100;  const int* p = &i;  int* q = const_cast<int*>(p);  …}// removing const modifier

(4)Constructors

The construction of a value of type T from a value e can be expressed by the notation T(e) or T{e}.
When e is omitted, T( ) or T{ } is used to express the default value of type T .

T(expression)  T{expression} 
   type cast – T is a simple form id.


   another notation for type cast 
 (T) expression
 float f;  int(f) or (int) f
 (unsigned int) f       


(5)Statement summary

A. Declaration statement
B. Try       
C. Catch   
D. Range for


(6)Declaration statements

A. Declarations in Conditions

if (double d=prim(true)) {    left /= d;    break;}// Scope of identifier declared in condition extends to the end of the statement that condition controls.// Only one id can be declared in this place.
B. Declarations in for Statements
for (int i=0;i<100;i++)  …// Scope of identifier declared in for statement extends to the end of this for statement.
C. range for statement P82-84

(7)Comments

A. Line comment
 // this is a line comment
B. Block comment
           /*  this is a multiline
                block comment    */



4. Functions

(1)Function declaration


(2)Inline functions 对于较短的代码来说,使用inline可以减少函数调用,加快程序速度(但需要更多的内存空间的使用,是用空间换时间的方法)

A function can be defined to be inline.
inline int f(int n)
{return n<2 ? 1 : n * f(n-1);}
This is a hint (not command) to the compiler that it should attempt to generate code for every function call.
The semantic of the function is not changed.

Generally speaking, an inline function improves efficiency, but increases the length of the executable file.
Commonly, functions with a few lines should be inlined. Otherwise, large functions should not be inlined.


(3)Argument passing P187-199

A. Call by Value


B. Call by Reference

Usage 1: Modification of arguments
Usage 2: Efficiency (using const T& )

C. const形参和实参

For T& :
    The type of argument must match exactly with that of parameter, argument must be a variable. 
For const T&:
    The argument may be a literal, a constant or temporary object generated by a type conversion.

 float fsqrt(const float&);// const引用传参 double d; float r = fsqrt(2.0f);//t.o. r = fsqrt(r); r = fsqrt(d); // t.o. float fsqrt(float&);// 普通引用传参 double d; float r = fsqrt(2.0f); //ERROR!! r = fsqrt(r); r = fsqrt(d); // ERROR!

(4)Value return

The semantic of function return is  initialization (not assignment) too.
A return statement is considered to initialize a temporary object of the function type.
Don't return pointers or references to local variables!
Often use “move” semantic instead of  “copy”

 float fsqrt(const float& r) { float x;   …   return x;    // float temp=x; }  float d; float r= fsqrt(d);   // r=temp, then temp is destroyed.  // temp may be optimized away   // by some compilers. 
 float* fp() { float local;   …   return &local;   // bad! }  float& fr() { float local;   …   return local;    // bad! } 

(5)Overloaded functions P206-211

A. Overloading Resolution Rules

[1] Exact match;
[2] Match using promotions;
[3] Match using standard conversions;
[4] Match using user-defined conversions;
[5] Mismatch, function undeclared.
 If two matches are found at the highest level where a match is found, the function call is rejected as ambiguous.

 void print(double); void print(long); print(1L);  // print(long) print(1.0); // print(double) print(1);     // standard conversion : int→double, int→long // ambiguous: print(long(1)) or print(double(1))? void print(double); void print(long); print(1);     →  print(static_cast<double>(1));   Or  print(static_cast<long>(1));  
B. Overloading Resolution for Multiple Arguments

 int    pow(int   ,int   );  double pow(double,double); double d = pow (2.0 , 2);//best match for arg1 is the second//best match for arg2 is the first// ambiguous!
C. Overloading and Scopes

// Functions declared in different non-namespace // scopes do not overloaded. [namespace chap8]  void f(int); void g() {     void f(double);    f(1);   // f(double) }

(6)Default arguments P211-213

A. A default argument is type checked at the time of the function declaration and evaluated at the time of the call.

 int g(int); void f(int = g(5));  // type checking f(); // default value computing 

B. Default arguments my be provided for trailing arguments only. 只能设置尾部参数的默认值

void f1(int, int=0, char* =0);void f2(int, int=0, char* );  // Error!void f3(int=0, int, char* =0);      // Error!

C. A default argument cannot be repeated or changed in a subsequent declaration in the same scope. 不能在同一个域中重复定义或改变参数默认值

void f(int = 7);void f(int);void f(int = 7); // error!void f(int = 8); // error!void g(){  void A::f(int x = 9);    // another function   …}


5. Namespaces and Exceptions P695-710

(1)What is namespace? P695-696

A. Name Clashes  

B. Namespace Definitions

 namespace my { char f(char); struct String {…}; } namespace your { char f(char); struct String {…};  }// some.cpp #include "my.h" #include "your.h" my::String s; your::f('a');
C. Definition of a Function of a Namespace

Inside  namespace definition
Outside namespace definition
      return-type  namespace::function(…)
      {…}


(2)Namespaces usages

Using from same namespace
      no special treatment is needed
Using from other namespaces P74
      -- qualified names

 namespace My {     int a;    void f() { a = 1; } }  My::f();// 写出命名空间My
      -- using declaration

 namespace My {  int a;    void f() { a = 1; } } void g() {  using My::f;// using声明    // introduce a local synonym     f(); }
      -- using directive

 namespace My {  int a;    void f() { a = 1; } } void g() {  using namespace My;// 直接访问    // introduce all members in My namespace    f();    a=1; }

(3)Unnamed namespaces P700

(4)Name lookup P705-708

 // a function can take arguments from more than one namespace. // look for in the scope of the call and in the namespaces of every argument. //  do the usual overload resolution of all functions found. void f(Chrono::Date d, std::string s) { if (d==s)…    //operator==(d,s) } // look for == in scope of  f, namespace Chrono and std. Chrono::operator== and std:: operator ==  are found,  // the result of overloading resolution is :   Chrono:: operator ==

(5)Namespace aliases P702

(6)Namespace composition and selection

A. Composition – merge of two or more namespaces
    -- Use using directive

 namespace My {  int a;    void f(); } namespace Other {  using namespace My;    void g(); } // composition of My and Other void someFunction() {    Other::a = 1;   Other::f();// 可以直接用命名空间Other使用f()   Other::g(); }// only if we need to define // something, do we need to know// the real namespace  void Other::f() // error! 当需要定义时才需要用到真正的命名空间My()  { … }   void My::f()  { … }    

B. Selection – define a new namespace that is composed by partial members of an existing namespace.
    -- Use using declaration

 namespace Old { class string { … }; String f(const string&, const string&); String f(const string&, const char*); // a lot of other names} namespace Selection { using Old::string; using Old::f; // 2 overloaded functions}

(7)Namespaces and overloading P708-710

// overloading does work across namespaces. namespace A { void f(int); } namespace B { void f(char);} using namespace A; using namespace B; f('a'); // B::f

(8)Namespaces are openP696 // 命名空间可以是不连续的

(9)Exceptions P172-173

(10)Throw and Catch P173-174 P687-689

A. throw

B. catch & try



6. Source Files and Programs

(1)Separate compilation and compilation unit

(2)Linkage 

A. Nonlocal names 非局部的命名with external linkage must be used consistently across all compilation units. 

// file1.cpp int x=1; int f() {…}// file2.cpp extern int x; int f(); void g() { x=f();} // correctly compiling file1.cpp  // and file2.cpp. // correctly linking.
// file1.cpp int x=1; int b=1; extern int c;// file2.cpp int x; extern double b; extern int c; // correctly compiling file1.cpp  // and file2.cpp. // incorrectly linking. Three problems.
// file1.cpp int x=1; int f() { return x; } // file2.cpp int x; int g() { return f(); } // correctly compiling file1.cpp  // incorrectly compiling file2.cpp. // incorrectly linking.  // correctly compiling and linking in C.
B. Two Linkage Modes

External Linkage – a name can be used in another compilation unit.
Internal Linkage – a name can only be used in the compilation unit in which it is defined.
Inline function, constants and typedef aliases have internal linkage.
In C, static global has internal linkage.

A constant name can be given external linkage by an explicit declaration:// 常量是内部链接,但通过extern的声明可以执行external linkage       // file1.cpp          extern const int a =11;       // file2.cpp          extern const int a;          void g() { /* can use a in this function */ } 
// file1.c 未命名的命名空间仅在本文件中可见,可以避免不同文件中静态全局变量出现冲突 namespace {   class X{…};   void f();   int i; }// Don't use static global in C++ !
C. Maintaining Consistency of Internal Linkage Names


(3)One definition rule

A given name must be defined exactly once in a program.
ODR – two definitions of a class,template or inline function are accepted as the same unique definition if and only if:
 [1] they appear in different compilation units, and
 [2] they are token-to-token identical, and
 [3] the meaning of those tokens are the same in both compilation units.


(4)Linkage to non-C++ code



(5)Include guards

If you include (directly or indirectly) the same header file in a compilation unit twice, then you violate ODR.Example:   //a.h    struct T {…};  // file.cpp    #include "a.h"    #include "a.h" // compiling file.cpp incorrectly.Solution : use include guard
  #ifndef SOMEHEADER_H  #define SOMEHEADER_H struct T {…}; … #endif// use long macro generally

(6)Alternative to global names



0 0
原创粉丝点击