打赏

5.2-day02-C++/内联/动态内存分配/引用/显示类型转换

九、
3.内联
1)编译器用函数的二进制代码替换函数调用语句,减少函数调用的时间开销。这种优化策略成为内联。
2)频繁调用的简单函数适合内联,而稀少调用的复杂函数不适合内联。
3)递归函数无法内联。
4)通过inline关键字,可以建议编译对指定函数进行内联,但是仅仅是建议而已。
inline void foo (int x, int y){...}
十、C++的动态内存分配
malloc/calloc/realloc/free
1.new/delete:对单个变量进行内存分配/释放
2.new[ ]/delete[ ]:对数组进行内存分配/释放
十一、引用
1.引用即别名。
int a = 20;
int& b = a; // int* b = &a;    引用的本质就是指针
b = 10; // *b = 10;
cout << a << endl; // 10 
2.引用必须初始化。
int a;
int* p;
a = 20;
p = &a;
int& b; // ERROR !
int& b = a; // OK
3.引用一旦初始化就不能再引用其它变量。
int a = 20, c = 30;
int& b = a;
b = c; // c => b/a
4.引用的应用场景
1)引用型参数
a.修改实参
b.避免拷贝,通过加const可以防止在函数中意外地修改实参的值,同时还可以接受拥有常属性的实参。
2)引用型返回值
int b = 10;
int a = func (b);
func (b) = a;
从一个函数中返回引用往往是为了将该函数的返回值作为左值使用。但是,一定要保证函数所返回的引用的目标在该函数返回以后依然有定义,否则将导致不确定的后果。
不要返回局部变量的引用,可以返回全局、静态、成员变量的引用,也可以返回引用型形参变量本身。
5.引用和指针
1)引用的本质就是指针,很多场合下引用和指针可以互换。
2)在C++层面上引用和指针存在以下不同:
A.指针式实体变量,但是引用不是实体变量。
int& a = b;
sizeof (a); // 4
double& d = f;
sizeof (d); // 8
B.指针可以不初始化,但是引用必须初始化。
C.指针的目标可以修改,但是引用的目标的不能修改。
D.可以定义指针的指针,但是不能定义引用的指针。
int a;
int* p = &a;
int** pp = &p; // OK
int& r = a;
int&* pr = &r; // ERROR
E.可以定义指针的引用,但是不能定义引用的引用。
int a;
int* p = &a;
int*& q = p; // OK
int& r = a;
int&& s = r; // ERROR
F.可以定义指针的数组,但是不能定义引用的数组。
int a, b, c;
int* parr[] = {&a, &b, &c}; // OK
int& rarr[] = {a, b, c}; // ERROR
可以定义数组的引用。
int arr[] = {1, 2, 3};
int (&arr_ref)[3] = arr; // OK
十二、显示类型转换运算符
C:目标类型变量 = (目标类型)源类型变量;
1.静态类型转换
static_cast<目标类型> (源类型变量)
如果在目标类型和源类型之间某一个方向上可以做隐式类型转换,那么在两个方向上都可以做静态类型转换。反之如果在两个方向上都不能做隐式类型转换,那么在任意一个方向上也不能做静态类型转换。
int* p1 = ...;
void* p2 = p1;
p1 = static_cast<int*> (p2);
char c;
int i = c;
如果存在从源类型到目标类型的自定义转换规则,那么也可以使用静态类型转换。
2.动态类型转换
dynamic_cast<目标类型> (源类型变量)
用在具有多态性的父子类指针或引用之间。
3.常类型转换
const_cast<目标类型> (源类型变量)
给一个拥有const属性的指针或引用去常
const int a = 100;
const int* p1 = &a;
*p1 = 200; // ERROR
int* p2 = const_cast<int*> (p1);
*p2 = 200; // OK
4.从解释类型转换
reinterpret_cast<目标类型> (源类型变量);
在不同类型的指针或引用之间做类型转换,以及在指针和整型之间做类型转换。
5.目标类型变量 = 目标类型(源类型变量);
int a = int (3.14);
十三、C++之父的建议
1.少用宏,多用const、enum和inline
#define PAI 3.141519
const double PAI = 3.14159;
#define ERROR_FILE -1
#define ERROR_MEM  -2
enum {
  ERROR_FILE = -1,
  ERROR_MEM = -2
};
#define max(a,b) ((a)>(b)?(a):(b))
inline int double max (double a, double b) {
  return a > b ? a : b;
}
2.变量随用随声明同时初始化。
3.少用malloc/free,多用new/delete。
4.少用C风格的强制类型转换,多用类型转换运算符。
5.少用C风格的字符串,多用string。
6.树立面向对象的编程思想。
++C
第二课  类和对象
一、什么是对象
1.万物皆对象
2.程序就是一组对象,对象之间通过消息交换信息
3.类就是对对象的描述和抽象,对象就是类的具体化和实例化
二、通过类描述对象
属性:姓名、年龄、学号
行为:吃饭、睡觉、学习
类就是从属性和行为两个方面对对象进行抽象。
三、面向对象程序设计(OOP)
现实世界                 虚拟世界
对象    -> 抽象 -> 类 -> 对象
1.至少掌握一种OOP编程语言
2.精通一种面向对象的元语言—UML
3.研究设计模式,GOF
四、类的基本语法
1.类的定义
class 类名 {
};
class Student {
};
2.成员变量——属性
class 类名 {
  类型 成员变量名;
};
class Student {
  string m_name;
  int    m_age;
};
3.成员函数——行为
class 类名 {
  返回类型 成员函数名 (形参表) {
    函数体;
  }
};
class Student {
  string m_name;
  int    m_age;
  void eat (const string& food) {
    ...
  }
};
4.访问控制属性
1)公有成员:public,谁都可以访问。
2)私有成员:private,只有自己可以访问。
3)保护成员:protected,只有自己和自己的子类可以访问。
4)类的成员缺省访控属性为私有,而结构的成员缺省访控属性为公有。

1.c
  1. #include<iostream>
  2. usingnamespace std;
  3. int main (void){
  4. cout <<"Hello, World !"<< endl;
  5. return0;
  6. }
 

1.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. int main (void){
  4. auto i =10;
  5. auto f =3.14;
  6. cout << i <<' '<< f << endl;
  7. return0;
  8. }
 用2011编译器去编译;
 g++ 11.cpp -std=c++0x

const.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. int main (void){
  4. constvolatileint a =100;
  5. // a = 200;
  6. constvolatileint* p1 =&a;
  7. // *p1 = 200;
  8. int* p2 =const_cast<int*>(p1);
  9. *p2 =200;
  10. cout <<*p2 << endl;// 200
  11. cout << a << endl;// 200
  12. // cout << 100 << endl;
  13. return0;
  14. }
  强制类型转换:放弃一切安全机制;
  目标类型变量=(目标类型) 源类型变量;
 C++编译器:静态编译器;
 静态:static_cast
 动态:dynamic_cast
 
【给一个拥有const属性的指针或引用去常,去掉常属性】
  const 只读属性
 
 
const int a = 100;   //常量优化
不管a是多少,a都为100,打出a的字面值,用100去优化;
 
const volatile int a = 100;
 别做优化,会用a的值输出;
 用volatile保证不做寄存器优化,常量优化的值;
保证访问的是内存中的值,而不是历史值;
 new返回的是数组的首地址;
 

new.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. int main (void){
  4. // int* pi = (int*)malloc (sizeof (int));
  5. // free (pi);
  6. int* pi =newint;
  7. *pi =1000;
  8. cout <<*pi << endl;
  9. delete pi;
  10. pi = NULL;
  11. /*
  12. *pi = 2000;
  13. cout << *pi << endl;
  14. */
  15. pi =newint[10];
  16. for(size_t i =0; i <10;++i)
  17. pi[i]= i;
  18. for(size_t i =0; i <10;++i)
  19. cout << pi[i]<<' ';
  20. cout << endl;
  21. delete[] pi;
  22. pi = NULL;
  23. pi =newint(1234);
  24. cout <<*pi << endl;
  25. delete pi;
  26. pi = NULL;
  27. char buf[4]={0x12,0x34,0x56,0x78};
  28. pi =new(buf)int;
  29. cout << hex <<*pi << endl;
  30. // delete pi;
  31. cout <<(void*)pi <<' '<<(void*)buf << endl;
  32. int(*p)[4]=newint[3][4];
  33. delete[] p;
  34. int(*q)[4][5]=newint[3][4][5];
  35. delete[] q;
  36. return0;
  37. }
 new/delete:对单个变量进行内存分配/释放;
 new[]/delete[]:对数组进行内存分配/释放;
 
new  int[3][4]  返回的是一个二维数组第一个元素的地址;
 
 
三维数组:二维数组的数组
int (*p) [4] = new   int [3][4];
用二维数组的指针去接受三维数组;   
 
动态内存分配:
string自动维护内存,无内存限制; “\0”,且自动添加 ‘\0’
 
对单个变量:
 
对数组:
 malloc在堆里释放内存,只malloc不free, 称为内存的泄露;
   int  *pi = new int;
  new:对单个变量进行内存的分配;
  野指针:存着一个地址,但里面标识的内存已经被释放;
  
  以数组方式new的,要用delete[] 删掉;
  pi = new int [10];
 ......delete[] pi;
 
  delete    pi;   局部释放
  delete[ ] pi;  全部释放
  
 pi = new int (1234);    new的同时赋初值; 栈内存不能delete;
 pi = new (buf)int;        以buf为首的,int大小区域;

reinter.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. int main (void){
  4. int i =0x12345678;
  5. char* p =reinterpret_cast<char*>(&i);
  6. for(size_t i =0; i <4;++i)
  7. cout << hex <<(int)p[i]<<' ';
  8. cout << endl;
  9. float* q =reinterpret_cast<float*>(&i);
  10. cout <<*q << endl;
  11. void* v =reinterpret_cast<void*>(i);
  12. cout << v << endl;
  13. return0;
  14. }
 reinterpret_cast <> (  ) //重解释类型转换-同一个内存,从不同角度(不同指针类型去看),对风马牛不相及的指针进行转化;
 

 
retref.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. int g_data =100;
  4. int& foo (void){
  5. return g_data;
  6. }
  7. int& bar (void){
  8. int a =100;
  9. return a;
  10. }
  11. int& fun (void){
  12. int b =200;
  13. return b;
  14. }
  15.  
  16. int& hum (int& a){
  17. return a;
  18. }
  19. int main (void){
  20. int data = foo ();
  21. cout << data << endl;// 100
  22. foo ()=200;
  23. cout << g_data << endl;
  24. foo ()+=100;
  25. ++foo ();
  26. cout << g_data << endl;// 301
  27. int& a = bar ();
  28. fun ();
  29. cout << a << endl;// 200
  30. return0;
  31. }
  
 
 
  int b = 10;
  int a = func(b);     返回右值;
  func(b) = a;          返回左值;
 
  foo ( ) = 200;    //200赋给临时变量;
 
  int & foo (void) {
   return g_data;
   }
   // 200赋给g_data了,此时赋的是别名int & foo (void);

static.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. int main (void){
  4. int* p1 = NULL;
  5. void* p2 = p1;
  6. p1 =static_cast<int*>(p2);
  7. return0;
  8. }
指针p2进行静态类型转换:
 p1 = static_cast<int*> (p2);
 

 
string.cpp
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. usingnamespace std;
  5. int main (void){
  6. string s1 ("hello");
  7. string s2 ="world";
  8. (s1 +=" ")+= s2;
  9. cout << s1 << endl;
  10. string s3 = s1;
  11. cout << s3 << endl;
  12. cout <<(s1 == s3)<< endl;
  13. s3[0]='H';
  14. cout << s3 << endl;
  15. cout <<(s1 > s3)<< endl;
  16. cout << s1.length ()<< endl;
  17. cout <<(s1 == s3)<< endl;
  18. cout << (strcasecmp (s1.c_str (),
            s3.c_str ()) == 0) << endl;
    cout <<sizeof(s1)<< endl;
  19. FILE* fp = fopen ("string.txt","w");
  20. // fwrite (&s3, sizeof (s3), 1, fp);
  21. fwrite (s3.c_str (),sizeof(char),
  22. s3.length (), fp);
  23. fclose (fp);
  24. return0;
  25. }
 
  1. cout <<(strcasecmp (s1.c_str (),
  2. s3.c_str ())==0)<< endl;
 不区分大小写进行比较,因为要求用char类型,所以用s1.c_str()和s3.c_str()
 

student.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. classStudent{
  4. private:
  5. string m_name;
  6. int m_age;
  7. public:
  8. void eat (const string& food){
  9. cout << m_age <<"岁的"<< m_name
  10. <<"同学正在吃"<< food <<"。"<< endl;
  11. }
  12. void setName (const string& name){
  13. if(name =="2")
  14. cout <<"你才"<< name <<"!"<< endl;
  15. else
  16. m_name = name;
  17. }
  18. void setAge (int age){
  19. if(age <0)
  20. cout <<"无效的年龄!"<< endl;
  21. else
  22. m_age = age;
  23. }
  24. };
  25. int main (void){
  26. Student student;
  27. student.setName ("2");
  28. student.setAge (-100);
  29. student.setName ("张飞");
  30. student.setAge (20);
  31. student.eat ("包子");
  32. return0;
  33. }
 

 
swap.cpp
  1. #include<iostream>
  2. usingnamespace std;
  3. void swap1 (int a,int b){
  4. int c = a;
  5. a = b;
  6. b = c;
  7. }
  8. void swap2 (int* a,int* b){
  9. int c =*a;
  10. *a =*b;
  11. *b = c;
  12. }
  13. void swap3 (int& a,int& b){
  14. int c = a;
  15. a = b;
  16. b = c;
  17. }
  18. void swap4 (constchar* x,constchar* y){
  19. constchar* z = x;
  20. x = y;
  21. y = z;
  22. }
  23. void swap5 (constchar** x,constchar** y){
  24. constchar* z =*x;
  25. *x =*y;
  26. *y = z;
  27. }
  28. void swap6 (constchar*& x,constchar*& y){
  29. constchar* z = x;
  30. x = y;
  31. y = z;
  32. }
  33. structStudent{
  34. char name[1024];
  35. int age;
  36. };
  37. void print (conststructStudent& s){
  38. cout << s.name <<","<< s.age << endl;
  39. // s.age = -1;
  40. }
  41. void foo (constint& x)
  42. cout << x << endl;
  43. }
  44. int main (void){
  45. int a =100, b =200;
  46. // swap1 (a, b);
  47. // swap2 (&a, &b);
  48. swap3 (a, b);
  49. cout << a <<' '<< b << endl;// 200 100
  50. constchar* x ="hello",*y ="world";
  51. // swap4 (x, y);
  52. // swap5 (&x, &y);
  53. swap6 (x, y);
  54. cout << x <<' '<< y << endl;
  55. Student s ={"张飞",22};
  56. print (s);
  57. print (s);
  58. foo (100);
  59. return0;
  60. }
 引用:
 swap3 (a, b);     -> void swap3 (int& a, int& b)  {......}
 
指针:
void swap5 (constchar** x,constchar** y)
要用二级指针,即,const char ** x 
 
引用型参数:
void print (conststructStudent& s)
&符号避免拷贝的开销;提高了效率;
 避免拷贝,通过加const可以防止在函数中意外地修改实参的值,
 同时还可以接受拥有常属性的实参。
 
 
 
 
 
 
 
 

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">





posted on 2018-11-29 22:58  XuCodeX  阅读(196)  评论(0编辑  收藏  举报

导航