美文网首页
C++ Primer 读书笔记:(P247-294)

C++ Primer 读书笔记:(P247-294)

作者: __小赤佬__ | 来源:发表于2019-03-15 14:42 被阅读0次

昨天翻开了这本书,今天竟然又翻开了!看来我还是挺有意志力的!
Array & Const的内容特别繁琐,我瞎看了一些,以后具体遇到还是需要回来复习的。

Exception Handling

In general, bypassing part of the program might mean that an object is left in an invalid or incomplete state, or that a resource is not freed, and so on.

  • throw
// first check that the data are for the same item 
if (item1.isbn() != item2.isbn())
   throw runtime_error("Data must refer to same ISBN"); // if we're still here, the ISBNs are the same
cout << item1 + item2 << endl;
  • try
while (cin >> item1 >> item2) { 
   try {
  // execute code that will add the two Sales_items
  // if the addition fails, the code throws a runtime_error exception 
  } catch (runtime_error err) {
  // remind the user that the ISBNs must match and prompt for another pair 
  cout << err.what()
  << "\nTry Again? Enter y or n" << endl; 
  
  char c;
  cin >> c;
  if (!cin || c == 'n')
    break; // break out of the while loop }
}

The catch block is searched from the closest function to further(outwards).
If no appropriate catch is found, execution is transferred to a library function named terminate.

We can only default initialize exception, bad_alloc, and bad_cast objects; it is not possible to provide an initializer for objects of these exception types. The other exception types have the opposite behavior: We can initialize those objects from either a string or a C-style string, but we cannot default initialize them.

The exception types define only a single operation named what. That function takes no arguments and returns a const char* that points to a C-style character string. The purpose of this C-style character string is to provide some sort of textual description of the exception thrown.

Function

  • Automatic objects: Objects that exist only while a block is executing are known as automatic objects. After execution exits a block, the values of the automatic objects created in that block are undefined. Such as parameters & local variables.
  • Local static object: Each local static object is initialized before the first time execution passes through the object’s definition. Local statics are not destroyed when a function ends; they are destroyed when the program terminates.
size_t count_calls()
{
    static size_t ctr = 0; // value will persist across calls
    return ++ctr; 
} 

// will print from 1 to 10
int main()
{
    cout << count_calls() << endl;
    for (size_t i = 0; i != 10; ++i) return 0;
}
  • Programmers accustomed to programming in C often use pointer parameters to access objects outside a function. In C++, programmers generally use reference parameters instead.
  • Ignoring top-level const: In C++, we can define several different functions that have the same name. However, we can do so only if their parameter lists are sufficiently different. Because top-level consts are ignored, we can pass exactly the same types to either version of fcn. The second version of fcn is an error. Despite appearances, its parameter list doesn’t differ from the list in the first version of fcn.
void fcn(const int i) { /* fcn can read but not write to i */ } 
void fcn(int i) { /* . . . */ } // error: redefines fcn(int)

main

prog -d -o ofile data0
int main(int argc, char *argv[]) { ... } // argv is array of pointers to C char strings
int main(int argc, char **argv) { ... } // equivalent

argv[0] = "prog"; 
argv[1] = "-d"; 
argv[2] = "-o"; 
argv[3] = "ofile"; 
argv[4] = "data0"; 
argv[5] = 0;

Functions with Varying Parameters

  • initializer_list Parameters

Like a vector, initializer_list is a template type. When we define an initializer_list, we must specify the type of the elements that the list will contain:

initializer_list<string> ls; // initializer_list of strings 
initializer_list<int> li; // initializer_list of ints

Unlike vector, the elements in an initializer_list are always const values; there is no way to change the value of an element in an initializer_list.

void error_msg(initializer_list<string> il)
{
    cout << *beg << " " ;
    for (auto beg = il.begin(); beg != il.end(); ++beg) cout << endl;
}

if (expected != actual) error_msg({"functionX", expected, actual});
  • Ellipsis Parameters

Ellipsis parameters are in C++ to allow programs to interface to C code that uses a C library facility named varargs. Generally an ellipsis parameter should not be used for other purposes. Your C compiler documentation will describe how to use varargs.

An ellipsis parameter may appear only as the last element in a parameter list and may take either of two forms:

void foo(parm_list, ...); 
void foo(...);

Const & Array(need revisit)

  • Because we can’t change the value of a const object after we create it, it must be
    initialized
const int k; // error: k is uninitialized const
  • By Default, const Objects Are Local to a File. When we define a const with the same name in multiple files, it is as if we had written definitions for separate variables in each file.

I'm not sure about sharing const across files using extern

  • Const gala
const int ci = 1024; 
const int &r1 = ci; // ok: both reference and underlying object are const 
r1 = 42; // error: r1 is a reference to const
int &r2 = ci; // error: non const reference to a const object

int i = 42;
const int &r1 = i; // we can bind a const int& to a plain int object 
const int &r2 = 42; // ok: r1 is a reference to const
const int &r3 = r1 * 2; // ok: r3 is a reference to const
int &r4 = r * 2; // error: r4 is a plain, non const reference

int i = 42; 
int &r1 = i; // r1 bound to i
const int &r2 = i; // r2 also bound to i; but cannot be used to change i
r1 = 0; // r1 is not const; i is now 0
r2 = 0; // error: r2 is a reference to const

const double pi = 3.14; // pi is const; its value may not be changed 
double *ptr = &pi; // error: ptr is a plain pointer
const double *cptr = &pi; // ok: cptr may point to a double that is const 
*cptr = 42; // error: cannot assign to *cptr
double dval = 3.14; // dval is a double; its value can be changed 
cptr = &dval; // ok: but can't change dval through cptr

int errNumb = 0;
int *const curErr = &errNumb; // curErr will always point to errNumb 
const double pi = 3.14159;
const double *const pip = &pi; // pip is a const pointer to a const object

The fact that a pointer is itself const says nothing about whether we can use the pointer to change the underlying object. Whether we can change that object depends entirely on the type to which the pointer points. For example, pip is a const pointer to const. Neither the value of the object addressed by pip nor the address stored in pip can be changed. On the other hand, curErr addresses a plain, nonconst int.

  • Top level & low level const
    We use the term top-level const to indicate that the pointer itself is a const. When a pointer can point to a const object, we refer to that const as a low-level const.

相关文章

网友评论

      本文标题:C++ Primer 读书笔记:(P247-294)

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