最近开始看c++primer,做一点记录!

函数的基础知识:

要使用函数,必须完成:

1. 提供函数的定义

2.提供函数原型

3.调用函数

了解一下,函数是如何返回它的返回值:

函数会通过将返回值复制到指定的cpu寄存器或者内存单元中来将其返回,随后,调用程序将查看该内存单元,在这一过程中,返回函数和调用函数必须就该内存中存储的数据的类型达成一致,函数原型将返回值类型告知调用程序,而函数的定义决定被调函数应该返回什么类型的数据。在原型中提供与定义中相同的信息似乎有些多余,但是这样做确实有道理。例如要让信差从办公室的桌上取走一些物品,则向信差和办公室的同事都交代自己的意图,将提高信差完成这项工作的概率(C++ primer)

函数原型与函数定义:

函数原型: 即函数声明

函数定义: 函数的定义

1. c++中为什么需要提供函数原型

原型描述了函数到编译器的接口,也就是说,它将函数的返回值类型和参数的类型,数量告诉编译器。

例如函数原型:

double cube(double x);

首先,原型会告诉编译器cube()函数有一个double类型的参数,如果程序没有提供这样的参数,原型将让编译器能够捕获到这种错误。在cube()函数完成计算之后,将把返回值放到指定的位置(CPU寄存器或者内存中),然后调用函数(main()函数)将从这个指定的位置取得返回值,由于原型中指出了函数cube的返回值类型为double,因此编译器知道应该检索多少个字节以及如何解释它们。

这样做可以解决编译时的效率问题,如果没有函数原型,编译器在编译过程中在文件中查找函数的定义的话,会比较耗时,同时在查找的过程中会停止对main()函数的编译,而且函数很可能不在文件中,这样,编译器将无权访问函数代码。

所以,综上所述,原型可以确保以下几点:

1. 编译器正确处理函数的返回值

2. 编译器检查使用的参数数目是否正确

3. 编译器检查使用的参数类型是否正确

上述在编译阶段进行的原型化称为静态类型检查(static type checking)

函数和数组

数组做为函数的指针,将数组的首地址作为参数传递给函数,,节省可复制整个数组所需的内存空间和时间。尤其是在遇到大的数组的时候。

int sum(int array[], int size)
{int M = sizeof array;     // sizeof array返回的是指向数组元素的指针 的字节数(大小) // 指针本身并没有指出数组的长度
}
int main(int argc, char *argv[])
{const int arraySize = 8;int cookies[arraySize] = {1,2,3,4,5,6,7,8};int L = sizeof cookies;     // 这里返回的是整个数组的长度(字节数) int total = sum(cookies, arraySize);    return 0;
}

由于上面的原因,所以数组作为函数参数的时候必须显式的传递数组的大小

// 可以选择数组的起始和结束的位置
int total = sum(cookies+3, 4);   // 起始位置, 数组的长度  

在数组作为函数的参数时,使用const保护数组:

函数使用普通参数时,这种保护机制将自动实现,因为参数按值传递,使用的是实参的副本,但是当参数为数组时,应该考虑如何避免参数被修改。

// 使用const保护数组参数
void show_array(const double arr[], int n);

使用const限制数组参数,这意味着原始数组不一定得是常量,而是意味着不能再show_array()函数中修改数组中元素的值。

将数组的区间作为参数传入函数,在STL中,使用 “超尾” 的概念来指定区间,如数组名是指向数组第一个元素的指针,数组大小i为n,则数组名+n是执行数组中最后一个元素的后一个位置,所以会有“超尾”这个概念。

例如对之前的sum()函数做修改:

#include <iostream>
#include <algorithm>
using namespace std;int sum(const int* begin, const int* end)
{int total = 0;const int* pt;   // pt指向常量的指针 for(pt=begin; pt<end; pt++){total += *pt;} return total;
}int main(int argc, char *argv[])
{const int arraySize = 8;int cookies[arraySize] = {1,2,3,4,5,6,7,8};cout << sum(cookies, cookies+arraySize) << endl;;return 0;
}

关于const对指针的限制:
1. 可以用const来修饰指针,让指针指向一个常量对象,防止使用指针来修改指向元素的值

但是要注意:const *pt这样的声明,并不意味着pt指向的值实际就是一个常量,而实意味着对pt而言,这个值是一个常量,不能y用pt来修改他:

int age = 20;    // age不是一个常量
const int* pt = &age;   // pt指向的age值是一个常量。不能修改:
age += 10;    // 可以修改age的值
*pt += 10;    // 不能修改age的值 

2.第二种使用const的方式使得无法修改指针的值:

int age = 20;    // age不是一个常量
int* const pt = &age;   // 指针不能被修改,只能指向age
int sage = 80;
pt = &sage;     // 禁止这样修做! 

3. 第三种,可以声明指向const对象的const指针:

int age = 20;    // age不是一个常量
const int* const pt = &age;   // 指针不能被修改,只能指向age,且不能通过指针修改age的值

函数,二维数组

// 理解二维数组作为函数参数的原理

int data[3][4] = {{1,2,3,4},{2,3,4,5},{5,6,7,8}};
int sum(int arr[][4], int size)
{// 二维矩阵作为函数的参数// 参数arr相当于一个指针 ,指向数组的第一个元素,//这个数组的每一个元素都有四个元素组成,所以需要传入二维数组的列数//因此 arr[i]是一个由四个元素组成的数组的数组名int total = 0;for(int i=0; i<size; i++){for(j=0; j<4; j++){total += arr[i][j];}} return total;
}

函数与c-风格字符串

包含字符,但是不以空值字符结尾的char类型的数组只是数组,而不是字符串。意味着不必将字符串的长度传递给函数。

#include <iostream>
#include <algorithm>
using namespace std;unsigned int c_in_str(const char* str, char target)  // 寻找字符串中特定字符的个数
{unsigned int count = 0;while(*str)    // != '\0'{ if(*str == target){count++;}str++;}return count;
}int main(int argc, char *argv[])
{char ghost[15] = "helloworld";char* str = "helloworld";cout << c_in_str(ghost, 'o') << endl;cout << c_in_str(str, 'l') << endl;return 0;
}

返回c-风格的字符串

#include <iostream>
#include <algorithm>
using namespace std;char* build_str(char ch, int n)
{char* pstr = new char[n+1];     // new动态分配内存 pstr[n] = '\0';   // 字符串结尾while(n> 0){n--;pstr[n] = ch;} return pstr;
}
int main(int argc, char *argv[])
{char* p = build_str('M', 8);cout << p << endl;delete []p;     // 释放内存    return 0;
}

函数和结构体:

可以将一个结构赋值给另一个结构,也可以按值传递结构,就像普通变量一样。结构作为函数的参数,可以按值传递,但是按值传递的操作实际上函数中使用的是结构的副本(会将结构进行复制), 所以如果结构包含的数据量比较大的话,则复制结构需要增加内存需求,降低系统的运行速度。所以一般采用 pass by address 或者 pass by reference

#include <iostream>
#include <algorithm>
using namespace std;// 定义结构
struct travel_time
{int hour;int minute;travel_time(int hour, int minute){this->hour = hour;this->minute = minute;}travel_time(){this->hour = 0;this->minute = 0;}};const int minutes_perH = 60;
travel_time sum(travel_time, travel_time);    // 计算时间之和
void show_time(travel_time);     // 显示时间 int main(int argc, char *argv[])
{// travel_time time1 = {12, 45}; // 如果没有定义构造函数,则用这种方法初始化结构体 travel_time time1(12, 45);   travel_time time2(1, 35);        // 定义了构造函数的初始化方法 show_time(sum(time1, time2)); return 0;
}travel_time sum(travel_time t1, travel_time t2)
{travel_time total;total.minute = (t1.minute + t2.minute) % minutes_perH;total.hour = t1.hour + t2.hour + (t1.minute + t2.minute) / minutes_perH;return total;
}void show_time(travel_time t)
{cout << "The total time is: " << t.hour << ":" << t.minute << endl;
} 

坐标的转化:

#include <iostream>
#include <algorithm>
#include <cmath>using namespace std;struct rect
{double x;double y;rect(double x, double y){this->x = x;this->y = y;}rect(){this->x = 0;this->y = 0;}
};     // 定义结构struct polar
{double dist;double angle;polar(double dist, double angle){this->dist = dist;this->angle = angle;}polar(){this->dist = 0;this->angle = 0;}
}; // prototype
polar rect2polar(rect r)
{polar p;p.dist = sqrt(r.x*r.x + r.y*r.y);p.angle = atan2(r.y, r.x);return p;
}void show_polar(polar p)
{const double rad2degree = 180.0/3.1415;cout << "The distance is " << p.dist << endl;cout << "The degree is " << p.angle*rad2degree << endl;
}int main(int argc, char *argv[])
{rect r;polar p;cout << "Enter the rect.x and rect.y: ";while(cin >> r.x >> r.y){p = rect2polar(r);show_polar(p);cout << "Next two numbers:(q to quit)";}return 0;
}

运行结果:

while(cin >> x >> y), cin是一个istream对象, cin >> x也是一个istream对象,因此cin >> x >> y最终返回的也是一个istream对象(cin), 而cin在被用于测试表达式中时,将根据输入是否成功,被转换为bool型的true和false.所以如果输入q, cin将知道输入不正确,从而q将被留在队列中,并返回一个被转换为false的值。

递归与分治:

例:绘制标尺

#include <iostream>
#include <algorithm>
#include <cmath>using namespace std;// 绘制标尺
void subdivide(char ar[], int low, int high, int level)
{// 递归函数, 采用分治的方法 if(level == 0){return;}int mid = (low + high) / 2;ar[mid] = '|';subdivide(ar, low, mid, level-1);subdivide(ar, mid, high, level-1);
} int main(int argc, char *argv[])
{const int LEN = 66;const int divs = 6;char ruler[LEN];// 初始化rulerruler[LEN-1] = '\0';for(int i=1; i<LEN-2; i++){ruler[i] = ' ';} int min_index = 0;int max_index = LEN-2;ruler[min_index] = ruler[max_index] = '|';cout << ruler << endl;for(int i=1; i<=divs; i++){subdivide(ruler, min_index, max_index, i);cout << ruler << endl;// 将数组设置为空,以便进行下一次的分割for(int j=1; j<LEN-2; j++){ruler[j] = ' ';} }return 0;
}

运行结果:

------------------------------------------------------------------分割线------------------------------------------------------------------

c++知识整理 编程模块相关推荐

  1. CUDA编程基础知识整理

    CUDA编程基础知识整理 CUDA编程和GPU架构基本概念 CUDA核函数调度方式 前言:最近在尝试通过CUDA加速Swin Transformer,第一次接触CUDA的相关知识,将这些天学习到的内容 ...

  2. bazel 链接第三方动态库_C/C++编程知识:Linux 动态库相关知识整理

    动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序,动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执行程序等诸多好处.作者是一个Linux后台开发,这些知 ...

  3. keil C对lib封装库反汇编成C语言,Keil软件“C语言”及“汇编”混编 —— 相关知识整理.doc...

    Keil软件"C语言"与"汇编"混编 相关知识整理 用Keil在C中嵌入汇编1 在Keil中嵌入汇编2 介绍直接嵌入汇编代码的方法4 采用汇编可能会有的好处5 ...

  4. 安卓高级面试知识整理

                                                    安卓高级面试知识整理 Android 四大组件:这是一份全面 & 详细的Activity学习指南 ...

  5. *Java软件开发面试知识整理*

    Java软件开发面试知识整理 围绕以下几点回答问题:是什么.为什么.什么时候用.项目实现.解决什么问题.遇到的困难 谈谈你对Java和C的理解? Java: 面向对象.Unicode:可以跨平台(JV ...

  6. keil c语言pdf,Keil软件“C语言”与“汇编”混编 —— 相关知识整理.pdf

    Keil软件"C语言"与"汇编"混编 -- 相关知识整理.pdf Keil 软件软件C 语言语言与与汇编汇编混编混编 相关知识整理相关知识整理 用 Keil 在 ...

  7. Redis重点知识整理 -奔波儿东

    Redis重点知识整理 -奔波儿东 一.Redis简介: 1.什么是Redis? Redis(Remote Dictionary Server)是一个用c语言写的,开源的.高性能非关系型数据库.NoS ...

  8. python常用变量名_python基础知识整理

    Python Python开发 Python语言 python基础知识整理 序言:本文简单介绍python基础知识的一些重要知识点,用于总结复习,每个知识点的具体用法会在后面的博客中一一补充程序: 一 ...

  9. Spring AOP 知识整理

    为什么80%的码农都做不了架构师?>>>    AOP知识整理 面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足.在OOP中模块化的关键单元 ...

最新文章

  1. 论新时代软件测试人员的工作之道(三)让Code Review常态化
  2. python猜数字游戏编程、最后显示猜了几次_用Python完成猜数字游戏
  3. 【转】PB实现在通知区域添加图标
  4. 春节抽空读了8本书,只有这本书我1字不落的读完了!(上)
  5. 作者:孙卫强(1976-),男,博士,上海交通大学教授、博士生导师,主要研究方向为大数据网络、信息通信网等。...
  6. Spring-Data-JPA--增删改查2——自定义接口查询
  7. tomcat端口被占用问题完美解决方案!
  8. lua协程的使用列子分析
  9. 新手搭建网站服务器(Ubuntu+LAMP)
  10. 【AtCoder ABC 075 C】Bridge
  11. C++11 std::chrono库详解
  12. 努力做一个优秀的programmer [ C# 影院售票系统]
  13. mysql 随机取数组_sql语句实现随机取n条数据(转)
  14. ESET_VC52_UPID (nod32激活获取器)V4.2.0.9 绿色版
  15. python案例小游戏
  16. wps中有公式如何调整间距
  17. 计蒜客 - 猴子打字
  18. 【自动驾驶】华为车BU介绍(2021-11-23晚直播记录)
  19. 有关海盗湾墙外世界网站收藏
  20. 【php-fpm】重启、启动、关闭

热门文章

  1. k8s核心技术-Helm(安装和配置仓库)---K8S_Google工作笔记0045
  2. STM32工作笔记0059---独立看门狗实验
  3. JAVA实现Token学习笔记001--Token入门案例
  4. 微信公众开放平台开发06---复习一下servlet
  5. cocos之观察者模式应用实例
  6. 用汇编的眼光看C++(之嵌入汇编)
  7. 电大计算机理工英语19年秋季,国开电大理工英语1单元自测5形考任务答案
  8. python 安装包查询_Linux系统下查找安装包所在目录
  9. python椭圆曲线加密_如何理解椭圆曲线加密并对其进行编码
  10. PHP伪协议-文件包含漏洞常用的伪协议