1.7 c++_指针

1,指针和字符串
2,使用new来创建动态结构
3,自动、静态、动态存储
4,类型组合
5,数组的替代品

1,指针和字符串

char tests[20] = "tests";
const char* test1 = "test1";
char* test2;

cout << "字符串数组tests输出内容是:tests" << tests;
cout << "字符指针test1输出内容是:test1 " << test1;

test2 = tests;
cout << "字符指针test2输出内容诗test2:" << test2;
cout << "字符串tests的内存地址:"<< (int *)tests;
cout << "字符test1的指针地址和tests一样,指向同一个内存地址:" << (int *)test1;

test2 = new char[strlen(tests) + 1];//new一个test2,test2的长度和tests的长度相同,通过关键字strlen()来获取tests的长度,+1是为了给test2预留空格字符串的位置
strcpy(test2,tests);//将tests的内容复制给test2,通过关键字strcpy()来复制字符串内容
cout << "字符指针test2输出内容诗test2:" << test2;
cout << "字符串tests的内存地址:"<< (int *)tests;
cout << "字符串tests的内存地址:"<< (int *)tests;
cout << "字符test1的指针地址和tests不一样,因为使用了关键字new:" << (int *)test1;
delete[] test2;//释放内存

以上代码说明几点:
1,char数组的名字指向的是这个字符数组的内容

2,char指针初始化可以指向一个字符串,字符串”test1”能够直接赋值给上述代码中的char* test1,因为这个字符串“test1”表示的是字符串地址,所以能够直接使用=号赋值给char指针char* test1。

3,如果两个字符串之间使用=号来赋值,则他们的内存地址也一样

4,如果两个字符串使用new关键字来复制出一个字符串,则他们的内存地址不一样,虽然内容一样。

5,一般的打印一个指针,则会打印出指针指向的内存地址。但是char*指针打印的是它指向的字符串,如果要显示字符串的内存地址,则必须强转,如:(int *)tests;

6,使用关键字strcpy而不用=号来赋值,也是因为使用=号以后,无法获得新内存地址,即new test2的内存地址,而获得的是tests的内存地址。

注意:
1,有些编译器将字符串的字面值视为const,即常量。视图修改它们会导致运行阶段报错,但是不是所有的编译器都是这样。

2,有些编译器使用字符串字面值的一个副本来表示程序中的该字面值。

3,如果在给tests[10]赋值的时候,我们赋值超出了tests的范围,像这样:strcpy(tests,”12345678900”)。如果超出字符串范围,则会覆盖正在使用的其他内存。为了避免这种问题,我们可以使用,strcpy()的第三个参数,例如:strcpy(tests,”123456789000”,9); tests[9] = ‘\0’;
目标内存用完以后,不会添加空字符串,所以要在末尾手动添加空字符。

2,使用new创建动态结构

struct test{
    char name[20];
    int age;
    double price;
};

test* test1 = new test;
//->表示间接成员运算符
cin.get(test1->name,20);//从控制台输入一个字符串赋值给结构test的成员name,并规定输入长度为20
cin >> (*test1).age;//从控制台输入一个整型赋值给结构test的成员age
cin >> test1->price;//从控制台输入一个整型赋值给结构test的成员private

cout << "通过指向结构的指针test1访问结构成员name:"<< (*test1).name;
cout << "通过指向结构的指针test1访问结构成员age:" << test1->age;

delte test1;

当我们使用指针去访问某个结构中的某个成员的时候有两种方式:
test1->name;
(*test1).name;
输入方式同上

3,自动、静态、动态存储

c++有三种管理数据内存的方式,自动存储,静态存储,动态存储
1,自动存储
在函数内部定义的常规变量使用的是自动存储,它们是自动变量,他们在所属函数被调用时候产生,在该函数结束时消亡。
例如:

private:
    void test(){
        char temp[10];//自动变量,使用自动存储
        cin >> temp;
        cout << "当该函数走完的时候,temp也就此释放:" << temp;
    };

自动变量也是一种局部变量,作用域只在包含它的代码块

2,静态存储
程序执行期间一直存在的存储方式。
让变量成为静态的方式有两种,
1,在函数外面定义它
2,使用关键字static

3,动态存储
new和delete提供了动态存储的方式,比静态和自动变量更加灵活。

4,类型组合

//定义一个结构
struct test{
    int year;
};
//可以这样创建变量
test t1,t2,t3;

//给t1的成员赋值
t1.year = 1998;

//创建结构指针t4
test* t4 = &t1;

//通过指针赋值
t4->year = 1999;

//创建结构数组
test t5[3];

//反问结构数组中的成员
t5[0].year = 2000;

//犹豫数组名是一个指针,也可以这样访问成员
(t5 +1)->year = 2001;

//创建指针数组
const test* t6[3] = {&t1, &t2, &t3};

//通过间接成员运算符来访问指针数组中的成员
cout << "通过间接成员运算符访问指针数组中的成员:" << t6[0]->year;

//创建指向数组t6的指针,即创建指针的指针
const test** t7 = t6;
cout << (*t7)->year;//t7指向t6的第一个元素的内存地址,所以*t7就是第一个元素的值,即&t1。所以,可以(*t7)->year; = t6[0]->year;

cout << (*(t7 +1))->year;//指向t6的第二个元素的内存地址

//使用auto关键字来定义数组
auto t8 = t6;
cout << (*(t8 +1))->year;

5,数组的替代品

1,模板类vector
模板类vector类似于string是一种动态数组
可以在运行时动态设置长度,也可以在末尾附加新数据,也可以在中间插入新数据
它是用new创建的动态数组的替代品
vector的功能比数组强大,但是效率低

#include <vector>//添加使用模板类vector的头文件

vecotr<int> vi;//vi的初始长度为0,并且会根据插入或者添加值自动调整长度
int n;
cin >> n;
vector<double> vd(n);//vd的长度为n,它可以存储n个类型为double的元素

2,模板类array (c++ 11)
array存在命名空间std中,和数组一样,array的长度是固定的,使用栈(静态内存分配)的方式存储,所以它的效率和数组一样,但是更方便,更安全。

#include <array>//添加使用array的头文件
array<int,5> ai;
array<double,4> ad = {1.1,1.2,1.3,1.4};
//值得注意的是,第二个参数,即表示array长度的参数是一个常量,不能是变量

3,数组、vector、array相比较

#include <iostream>
#include <vector>
#include <array>

using namespace std;

int main(){
    double a1[4] = {1.2,1.3,1.4,1.5};
    vector<double> a2(4);//c++ 11允许vector对象用于列表初始化,但是c++98不能这样做
    a2[0] = 1d / 3d;
    a2[1] = 1.0 / 3.0;
    a2[2] = 3.5;
    a2[3] = 1d;
    array<double,4> a3 = {2.5,2.6,2.7,2.8};
    array<double,4> a4;
    a4 = a3;
    a1[-2] = 20.2;//这种写法将被转换成*(a1 - 2) = 20.2 。意思是找到a1所指向的地方,向前移动两个元素,并将20.2赋值。也就是说,信息存储到了数组的外面,c++和c一样,不会检查这种越界错误,所以这样做可能占用其他正在使用的内存。是不安全的操作
    a2[-2] = 0.5;//vector同上
    a3[300] = 1.5//array同上
    a2.at(1) = 2.3;//使用关键字at()将在运行期间捕获非法索引,代价是运行时间变长
    a3.begin();
    a2.end();//begin()和end()能够让你确定边界
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值