C++自学笔记_数组和指针_《C++ Primer》

  

  1.数据定义中的类型可以是内置数据类型或者类类型,除引用数据类型之外,数组元素的类型可是是任何数据类型。没有所有元素都是引用数据类型的数组。

  2.数组的维数必须要用值大于等于1的表达式定义。此常量表达式只能包含整形字面值常量枚举常量或者用常量表达式初始化的const对象,否则在编译阶段不知道数组的维数,对于一个非const对象,只有运行时才能获得它的值。  

const unsigned buf_size=512;
int staff_size=27;
char input_buffer[buf_size];    //ok:const variable
double salaries[staff_size];    //error:non const variable

  3.关于初始化

  若没有显示提供元素初值,则数组会像普通变量一样初始化:

  · 函数体外定义的内置数组,其元素均初始化为0

  · 函数体内定义的内置数组,其元素无初始化

  · 不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;

string sa[10];        //元素初始化为空字符串
int ia[10];              //元素初始化为0
int main(){
    string sa2[10];  //元素初始化为空字符串
    int ia2[10];        //无初始化
    return 0;
}

  4.关于void*指针

  C++提供了一种特殊的指针void*,它可以用来保存任何一种数据类型对象的地址。

double obj=3.14;
double *pd=&obj;
void *pv=&obj;  //ok:void* can hold the address value of any data pointer type
pv=pd;

  void*指针只支持几种有限的操作:与另一个指针进行比较;向函数传递void*指针或者从函数返回void*指针;给另一个void*指针赋值。

  注意:不允许使用void*指针操纵它所指向的对象。

   5.之前没有完全理解什么叫做“引用一旦初始化以后就不能再指向另一个对象”这句话。其实是这样子:C++规定定义引用必须立即马上进行初始化,而当我再次给引用赋值时(曾经我以为这是把引用指向另一个对象..),实际上再次给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联(这也就是引用为什么在定义时即必须初始化的原因)。

  6.指向const对象的指针

const double *cptr;

  这里的cptr是一个指向double型const对象的指针,也就是说,cptr本身并不是const,在定义它的时候不需要给他初始化。如果需要的话,也可以给cptr重新赋值,使其指向另一个const对象(此处要注意,可以把这种情况理解为:指向const对象的指针会自以为自己是指向const对象的指针,所以当再次给cptr赋值时,要是cptr指向的对象不再是const类型了,倒也不允许了呵呵)。

  把一个const对象的地址赋值给一个普通的、非const对象的指针也会导致编译时的错误。(所谓的指向const对象的指针也要具有const特性)。

const double pi=3.14;
double *ptr=π         //error
const double *cptr=π  //ok

  允许把非const对象的地址赋值给指向const对象的指针。

const double *cptr;
double dval=3.14;
cptr=&dval;       //ok:but can‘t change dval through cptr  

  cptr一旦定义,就不能通过cptr改变它所指向的值,但是并不是意味着cptr指向的非const对象就不可以修改了,可以通过普通的指向非const对象的指针进行修改。

  7.const指针

int errNum=0;
int *const curErr=&errNum;  //curErr is a constant pointer

  意味着curErr指针一旦初始化以后就再也不能指向别的对象。企图给任何const指针赋值的行为都会导致编译时的错误。但是,指针本事是const的事实并没有说明能否通过const指针修改它所指向的对象的值,能否修改完全取决于它所指的对象的类型。

  8.指向const对象的const指针

const double pi=3.14;
const double const *pi_ptr=π

  这么理解:首先,pi_ptr是个const指针,它又指向一个const对象。结果:既不允许修改pi_ptr所指向对象的值,也不允许修改pi_ptr的指向。

  9.创建动态数组

  动态数组并不是说数组的大小是可以变化的,而是指在编译的时候不必知道数组的长度,可以在运行的时候再确定数组的长度。并且,与数组变量不同的是,动态分配的数组将一直存在,直到程序显式释放它为之。
  :每一个程序在执行的时候都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的堆。C语言使用一对标准库函数malloc和free在堆中分配存储空间,C++语言使用new和delete表达式实现同样的功能。

  9.1动态数组的定义

  动态分配数组时,只需指定类型和数组长度即可,用不着给数组命名,new表达式返回的是指向分配的内存空间的第一个元素的指针。

int *pia=new int[10];

  9.2初始化动态分配的数组

  动态分配数组时,如果数组元素师类类型,那么调用类的默认构造函数进行初始化;如果数组元素是内置数据类型,那么不进行初始化(和上面的函数内和函数外数组变量的初始化区别开来)。

string *psa=new string[10];  //全部初始化为空字符串
int *pia=new int[10];        //不进行初始化

  

时间: 2024-10-08 10:09:11

C++自学笔记_数组和指针_《C++ Primer》的相关文章

C Primer Plus_第10章_数组和指针_编程练习

1. /*rain.c 针对若干年的降水量数据,计算年降水总量.年降水平均量,以及月降水平均量*/ #include <stdio.h> #define MONTHS 12 #define YEARS 5 int main (void) { //把数组初始化为2000到2004年的降水量数据 const float rain[YEARS][MONTHS] = //const声明和初始化数组可保护数据 { {4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4,

C语言学习_数组与指针2

数组其实是一种变相的指针,数组名同时也是指针,eg: CODE == &CODE[0]; 数组的加法: #include<stdio.h> #define SIZE 4 int main(void) { shortdates[SIZE]; short* pti; shortindex; doublebills[SIZE]; double* ptf; pti= dates;//把数组地址付给指针 ptf= bills; printf("%23s  %10s\n", &

C和指针 学习笔记-3.数组与指针

数据名代表首地址 指向数组的指针 #include <stdio.h> extern void iterate(int *p); void main(){ int a[]={1,2,3,4,5}; iterate(a); } void iterate(int *p){ int i; for(i=0;i<5;i++){ printf("%d",*p++); } } 指向一维数组的指针 int (*p)[3] #include <stdio.h> void i

网易云课堂_艾叔:零基础一站式C语言|C程序设计精讲_章节12:指针_课时63指针操作数组

二维数组 #include <stdio.h> #include <stdlib.h> int main() { int age[2][4] = { 1,2,3,4,5,6,7,8 }; int* p = &(age[0][0]); int i = 0; int j = 0; for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { printf("age[%d][%d] %p %d\n", i,

C++自学笔记_string测试编程题_《C++ Primer》

今天<C++ Primer>学完第9章,关于string类型,找道题目测试一下效果. 题目描述: 输入一个字符串,以回车结束(字符串长度<=100).该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写.现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串. 输入: 多组数据.每组数据输入包括3行, 第1行是包含多个单词的字符串 s, 第2行是待替换的单词a,(长度<=100) 第3行是a将被替换的单词b.(长度<=100) s, a, b 最前面和

Net基础篇_学习笔记_第九天_数组_三个练习

练习一: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _数组练习01 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 string str = null; 14 string[

Net基础篇_学习笔记_第九天_数组_冒泡排序(面试常见题目)

冒泡排序: 将一个数组中的元素按照从大到小或从小到大的顺序进行排列. for循环的嵌套---专项课题 int[] nums={9,8,7,6,5,4,3,2,1,0}; 0 1 2 3 4 5 6 7 8 9第一趟比较:8 7 6 5 4 3 2 1 0 9 交换了9次 i=0 j=nums.Length-1-i第二趟比较:7 6 5 4 3 2 1 0 8 9 交换了8次 i=1 j=nums.Length-1-i第三趟比较:6 5 4 3 2 1 0 7 8 9 交换了7次 i=2 j=nu

C++ Primer笔记12_运算符重载_递增递减运算符_成员访问运算符

1.递增递减运算符 C++语言并不要求递增递减运算符必须是类的成员.但是因为他们改变的正好是所操作对象的状态,所以建议设定为成员函数. 对于递增与递减运算符来说,有前置与后置两个版本,因此,我们应该为类定义两个版本的递增与递减运算符. 问题来了,程序是如何区分前置和后置呢?因为都是++和-- 为了解决这个问题,后置版本的递增递减运算符接受一个额外的(不被使用)int类型的形参.当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参.这个形参唯一的作用就是区分前置和后置运算符函数. 因为不会

C++ Primer笔记2_四种类型转换_异常机制

1.类型转换 命名的强制类型转换: 有static_cast.dynamic_cast.const_cast.reinterpret_cast static_cast: 编译器隐式执行的任何类型转换都可以由static_cast完成 当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换. 可以将void*指针转换为某一类型的指针 可以将基类指针强制转换为派生类指针,但是不安全. 无法将const转化为nonconst,这个只有const_cast才可以办得到 举例: