美文网首页
The C++(11) programming language

The C++(11) programming language

作者: Ewitter | 来源:发表于2019-04-02 23:17 被阅读0次

    代码均来自原书,笔记均贴原文,便于理解吧。

    1.char/signed char/unsigned char(p142-143)
    char c=255;  // 255 is ‘‘all ones,’’ hexadecimal 0xFF
    int i=c;
    
    On a machine where a char is unsigned, the answer is 255 . (answer means i)
    On a machine where a char is signed, the answer is −1 .
    In this case, the compiler might warn about the conversion of the literal
    255 to the char value −1 .
    
    However, C++ does not offer a general mechanism for detecting this kind of problem.
    One solution is to avoid plain char and use the specific char types only. 
    Unfortunately,some standard-library functions, such as strcmp() , take plain char s only.
    

    no pointer conversion among char/singed char/unsigned char

    A char must behave identically to either a signed char or an unsigned char . 
    However, the three char types are distinct, so you can’t mix pointers to different char types. 
    For example:
    
    void f(char c, signed char sc, unsigned char uc)
    {
        char∗ pc = &uc;  // error : no pointer conversion
        signed char∗ psc = pc;  // error : no pointer conversion
        unsigned char∗ puc = pc;  // error : no pointer conversion
        psc = puc;  // error : no pointer conversion
    }
    

    Variables of the three char types can be freely assigned to each other.
    However, assigning a too-large value to a signed char is still undefined.
    Unlike plain chars, plain ints are always signed.(p145)

    2.prefixs and suffixs(p147)
    c++4th6.2.6.png
    3.keywords(p156)
    c++4th6.3.3.1.png
    In addition,the word export is reserved ofr future use.
    4.A hidden global name can be reffered to using the scope resolution operator ::,for example(p158),
    int x;
    void f2()
    {
        int x;  //hide global x
        ::x=2;  //assign to global x
        x=2;  //assign to local x
    }
    
    int x=11;
    void f3()
    {
        int x=x;  //perverse:initialize x with its own (uninitialized)  value
    //like example of f3,good compiler warns if a variable is used before it has been initialized.
    }
    void f4()  //perverse:use of two different objects both called x in a single scope
    {
        int y=x;  //use global x: y=11
        int x=22;
        y=x;    //use local x:  y=22;
    }
    

    The names of function arguments are considered declared in the outermost block of a function.For example:

    void f5(int x)
    {
        int x;  //error; this is an error because x is defined twice in the same scope
    }
    
    5.Syntactic styles of Initialization(p159)
    X a1{v};  //this style is new in c++11
    X a2={v};
    X a3=v;
    X a4(v);
    

    The first style can be used in every context and does not allow narrowing.For example:

    void f(double val,int val2)
    {
        int x2=val;  //if val==7.9,x2 becomes 7
        char c2=val2;  //if val2==1025,c2 becomes 1
        int x3{val};    //error:possible truncation
        char c4{24};  //OK:0~255(8-bit chars) can be represented as a char
        int x4{2.0};  //error:no double to int value conversion
    }
    

    allowed conversion:char to int instead of int to char;int/float to float/double but not float/double to int/double,etc.

    6.we can use auto to get the type determined by the initializer.(p160)

    But the trap is that if the initializer is a {}-list,we may not want its type deduced.

    auto z1{99};  //z1 is an initializer_list<int>
    auto z2=99;  //z2 is an int
    
    vector<int> v1{99};  //v1 is a vector of 1 element with the value 99
    vector<int> v2(99);  //v2 is a vector of 99 elements each with the default value 0
    

    So prefer = when using auto.
    prefer {} initialization over alternatives unless you have a strong reason not to.

    The empty initializer list {},is used to indicated that a default value is desired:
    
    int x4{};  //x4 becomes 0
    double d4{};  //d4 becomes 0.0
    char* p{};  //p becomes nullptr
    vector<int> v4{};  //v4 becomes the empty vector
    string s4{};  //s4 becomes ""
    
    7.When using auto,a {}-list has its type deduced to std::Initializer_list<T>(p162)
    auto x1{1,2,3,4};  //x1 is an initializer_list<int>
    auto x2{1.0,2.25,3.5};  //x2 is an initializer_list of <double>
    auto x3{1.0,2};  //error:cannot deduce the type of {1.0,2}
    
    8.Deducing a type:auto and decltype() (p163)

    auto for deducing a type of an object from its initializer;the type can be the type of a variable,a const,or a constexpr.
    decltype(expr) for deducing the type of something that is not a simple initializer,such as the return type for a function or the type of a class member.

    use auto in small scopes unless there is a good reason not to.
    if a scope is large,mentioning a type explicitly can help localize errors.That is compared to using a specific type,using auto can delay the detection of type errors,for example:

    void f(double d)
    {
          constexpr auto max=d+7;
          int a[max];  //error: array bound not an integer.
          //...
    }
    

    if auto causes surprises,the best cure is typically to make functions smaller,which most often is a good idea anyway(§12.1).

    9.by using the {}-initializer syntax for such definitions ,we minimize the chances for unfortunate conversions.(p164)
    char v1{12345};  //error:narrowing
    int v2{'c'};  //fine:implicit char->int conversion
    T v3{f()};  //works if and only if the type of f() can be implicitly converted to a T
    
    When we use auto,there is onlu one type involved,
    the type of the initializer,and use the = syntax.
    
    auto v1=12345;  //v1 is an int
    auto v2='c';  //v2 is a char;
    auto v3=f();  //v3 is of some appropriate type
    
    10.Lifetime of objects(p167)

    Automatic:an object declared in a function is created when its definition is encounted and destoryed when its name goes out of scope.Objects like these are called automatic objects,and automatic objects are allocated on the stack,each call of the function gets its own stack frame to hold its automatic objects.

    Static:Objects declared in global or namespace scope and statics declared in functions or classes are created and initialized once (only) and "live" until the program terminates (and object has the same address throught the whole lifetime).These objects are called static objects.

    Free store:Using the new and delete operator,we can create objects whose lifetimes are controlled directly.(like malloc and free function in C)

    Temporary objects:(eg:intermediate results in a computation or an object used to hold value for a reference to const argument)Their use determines their lifetime.If objects are bound to a reference,their lifetime is that of the reference,otherwise "live" until the end of the full expression of which they are part.(temporary objects are automatic)

    Thread-local objects:objects declared thread-local,such objects are created when their thread is and destoryed when their thread is.

    11.Type aliases(p167)
    using Pchar=char*;  //pointer to character
    using PF=int(*)(double);  //pointer to function taking a double and returning an 
    
    typedef int int32_t;  //equivalent to "using int32_t=int;"
    typedef short int16_t;  //equivalent to "using int16_t=short;"
    

    The _t suffix is conventional for aliases("typedefs").int16_t,int32_t etc,can be found in <stdint>
    We cannot apply type specifiers,such as unsigned,to an alias.For example:

    using Char = char;
    using Uchar = unsigned Char;  //error
    using Uchar = unsigned char;  //OK
    
    12.Pointers(p172)
    For a type T,T* is the type "pointer to T".
    That is,a variable of type T* can hold the address of an object of type T,for example:
    
    char c='a';
    char* p=&c;  //p holds the address of c; & is the address-of operator
    
    The *,meaning "point to",is used as a suffix for a type name.
    Unfortunately,pointers to arrays and pointers to functions need a more complicated notation.
    
    int* p1;  //pointer to int
    char** ppc;  //pointer to pointer to char
    int* ap[15];  //array of 15 pointer to ints
    int (*fp)(char*);  //pointer to function taking a char* argument;returns an int
    int* f(char*);  //function taking a char* argument;returns a pointer to int 
    
    13.void*(p173)

    You can read void as pointer to an object of unknown type*.

    A pointer to any type of object can be assigned to a variable of type void*,
    but a pointer to function or a pointer to member cannot.
    
    A void* can be assigned to another void* and can be explicitly converted to another type.
    

    nullptr:a pointer that does not point to an object,and can be assigned to any pointer type.
    Zero (0) was used as a notation for the null pointer.Zero (0) is an int,the standard conversions allow 0 to be used as a constant of pointer or pointer-to member type.

    int* pi=nullptr;
    double* pd=nullptr;
    int* x=0;  //x gets the value nullptr
    
    It has been popular to define a macro NULL to represent the null pointer:
    
    int* p=NULL;  //using the macro NULL
    
    However,there are differences in the definition of NULL in different implementations;
    for example,NULL minght be 0 or 0L.
    In C,NULL is typically (void*)0,which makes it illegal in C++:
    
    int* p=NULL;  //error:can't assign a void* to int*
    
    14.Arrays(p174-p175)

    For a type T,T[size] is the type "array of size elements of type T",the elements are indexed from 0 to size-1.
    The number of elements of the array,the array bound,must be a constant expression.If need variable bounds,use a vector.For example:

    void f(int n)
    {
        int v1[n];  //error: array size not a constant expression
        vector<int> v2(n);  //OK:vector with n int elements
    }
    

    When an array is declared witihout a specific size,but with an initializer list,the size is calculated by counting the elements of the initializer list.

    If a size is explicitly specified,it is an error to give surplus elements in an initializer list.
    If the initializer supplier too few elements for an array,0 is used for the rest.
    
    int v5[8]={1,2,3,4};  //equivalent to int v5[]={1,2,3,4,0,0,0,0};
    

    No built-in copy operation for arrays.
    When you need assignment to a collection of objects,use a vector,an array,or a valarray instead.

    int v6[8]=v5;  //error:can't copy an array(can't assign an int* to an array)
    v6=v5;  //error:no array assignment
    
    15.String literals(p177)

    Long strings can be broken by whitespace to make the program text neater.

    char alpha[]="abcdefg"
        "_hijklmn";  //equivalent to char alpha[]="abcdefg_hijklmn";
    

    It is possible to have the null character in a string,but most programs will not suspect that there are characters after it.For example: the string "Jens\000Munk" will be treated as "Jens" by standard-library functions such as strcpy() and strlen().

    16.Raw character strings(p178)

    Raw string literals use the R"(ccc)" notation for a sequence of characters ccc.
    In contrast to nonraw string literals,a raw string literal can contain a newline:

    string counts {R"(1
    22
    333)"};  //equivalent to string x{"1\n22\n333"};
    

    Larger Character Sets:
    A string with the prefix L,such as L"angst",is a string of wide characters,its type is const wchar_t[].
    Similarly,string with prefix LR,such as LR"(angst)",is a raw string of wide characters of type const wchar_t[].

    A UFT-8 string is terminated by '\0',a UTF-16 string by u'\0',and a UTF-32 string by U'\0'.
    
    The order of the us and Rs and their cases are significant:RU and Ur are not valid string prefixs.
    
    17.Pointer to arrays(p180)
    c++4th7.4.png

    相关文章

      网友评论

          本文标题:The C++(11) programming language

          本文链接:https://www.haomeiwen.com/subject/ypoxjqtx.html