【CPP】指针

1- Pointers

Pointers

  • A pointer is declared like a variable, but with * after the type
  • What stored in a pointer variable is an address.
  • Operator & can take the address of an object or a variable of fundamental types
  • Operator * can take the content that the pointer points to

pointer.cpp

cpp 复制代码
#include <iostream>

using namespace std;

int main()
{
    int num = 10;
    int * p1 = NULL, * p2 = NULL; // declaration, initialize to 0
    p1 = &num; // take the address of num, assign to p1
    p2 = &num; // take the address of num, assign to p2

    cout << "num = " << num << endl;

    *p1 = 20; // assign to num
    cout << "num = " << num << endl;

    *p2 = 30; // assign to num
    cout << "num = " << num << endl;

    return 0;
}

Structure member accessing

  • p->member
  • (*p).member

pointer-struct.cpp

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;

struct Student
{
    char name[4];
    int born;
    bool male; 
};

int main()
{
    Student stu = {"Yu", 2000, true};
    Student * pStu = &stu;

    cout << stu.name << " was born in " << stu.born 
         << ". Gender: " << (stu.male ? "male" : "female") << endl;

    strncpy(pStu->name, "Li", 4);
    pStu->born = 2001;
    (*pStu).born = 2002;
    pStu->male = false;

    cout << stu.name << " was born in " << stu.born 
         << ". Gender: " << (stu.male ? "male" : "female") << endl;


    
    
    return 0;
}

Print out the address

  • Since the value of a pointer is an address, we can print it out
cpp 复制代码
    printf("Address of stu: %p\n", pStu); //C style
    cout << "Address of stu: " << pStu << endl; //C++ style
    cout << "Address of stu: " << &stu << endl;
    cout << "Address of member name: " << &(pStu->name) << endl;
    cout << "Address of member born: " << &(pStu->born) << endl;
    cout << "Address of member male: " << &(pStu->male) << endl;
  • The address should be an unsigned 32-bit or 64-bit integer
cpp 复制代码
    cout << "sizeof(pStu) = " << sizeof(pStu) << endl;

Pointers of Pointers

  • Pointers are variables, they also have address

pointer-pointer.cpp

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    int num = 10;
    int * p = &num;
    int ** pp = &p;
    *(*pp) = 20;

    cout << "num = " << num << endl;

    return 0;
}

Constant Pointers

const-pointer.cpp

cpp 复制代码
#include <iostream>
using namespace std;

int foo(const char * p)
{
    // the value that p points to cannot be changed
    // play a trick?
    char * p2 = p; //syntax error
    //...
    return 0;
}

int main()
{
    int num = 1;
    int another = 2;
    
    //You cannot change the value that p1 points to through p1
    const int * p1 = &num;
    *p1 = 3; //error
    num = 3; //okay

    //You cannot change value of p2 (address)
    int * const p2 = &num;
    *p2 = 3; //okay
    p2 = &another; //error

    //You can change neither
    const int* const p3 = &num;
    *p3 = 3; //error
    p3 = &another; // error

    return 0;
}

const int *: 不可以修改指针指向的内容

int * const: 不可以修改指针本身(地址)

const int * const: 既不可以修改指针指向的内容也不可以修改指针本身

const int * p;

char * p2 = p;

不能将const 的指针赋值给普通指针

2- Pointers and Arrays

  • Use & operator to get the address of elements

pointer-array.cpp

cpp 复制代码
#include <iostream>
using namespace std;

struct Student
{
    char name[4];
    int born;
    bool male; 
};

int main()
{
    // Part One
    Student students[128];
    Student * p0 = &students[0];
    Student * p1 = &students[1];
    Student * p2 = &students[2];
    Student * p3 = &students[3];

    printf("p0 = %p\n", p0);
    printf("p1 = %p\n", p1);
    printf("p2 = %p\n", p2);
    printf("p3 = %p\n", p3);

    //the same behavior
    students[1].born = 2000;
    p1->born = 2000;

    // Part Two
    printf("&students = %p\n", &students);
    printf("students = %p\n", students);
    printf("&students[0] = %p\n", &students[0]);
    
    Student * p = students;
    p[0].born = 2000;
    p[1].born = 2001;
    p[2].born = 2002;

    printf("students[0].born = %d\n", students[0].born);
    printf("students[1].born = %d\n", students[1].born);
    printf("students[2].born = %d\n", students[2].born);

    return 0;
}

Array name

  • You can consider an array name as a pointer

Pointer arithmetic

  • p + num or num + p points to the num-th element of the array p
  • p-num points to the -num-th element

arithmetic.cpp

cpp 复制代码
#include <iostream>
using namespace std;

#define PRINT_ARRAY(array, n) \
for (int idx = 0; idx < (n); idx++) \
    cout << "array[" << idx << "] = " << (array)[idx] << endl;

int main()
{
    int numbers[4] = {0, 1, 2, 3};
    PRINT_ARRAY(numbers, 4)

    int * p = numbers + 1; // point to the element with value 1
    p++; // point to the element with value 2

    cout << "numbers = " << numbers << endl;
    cout << "p = " << p << endl;

    *p = 20; //change number[2] from 2 to 20
    *(p-1) = 10; //change number[1] from 1 to 10
    p[1] = 30; //change number[3] from 3 to 30

    PRINT_ARRAY(numbers, 4)

    return 0;
}
  • The following are equivalent
cpp 复制代码
int i = ...;
int *p = ...;
p[i] = 3;
*(p  + i) = 3;
int *p2 = p + i;
*p2 = 3;
  • Be careful of out-of-bound
cpp 复制代码
int num = 0;
int * p = &num;
p[-1] = 2;   // out of bound
p[0] = 3;    // okay
*(p+1) = 4;   // out of bound

bound.cpp

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    int a;
    int num = 0;
    int * p = &num;

    p[-1] = 2; //out of bound
    p[0] = 3; //okay
    *(p+1) = 4; //out of bound

    cout << "num = " << num << endl;
    
    return 0;
}

程序越界

Differences between a pointer and an array

  • Array is a constant pointer
  • The total size of a ll elements in an array can be got by operator sizeof
  • sizeof operator to a pointer will return the size of the address (4 or 8)
cpp 复制代码
int numbers[4] = {0, 1, 2, 3};

int * p= numbers;
cout << sizeof(numbers) << endl;  // 4 * sizeof(int)
cout << sizeof(p) << endl;  // 4 or 8
cout << sizeof(double *) << endl;  // 4 or 8

3- allocate-memory: C style

Program memory

The address space of a program contains several data segments

  • Code: executable code
  • Data: initialized static variables
  • BSS: uninitialized static data including variables and constants
  • Heap: dynamically allocated memory
  • Stack: local variable, call stack

stack-heap.cpp

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    int a = 0;
    int b = 0;
    int c = 0;
    
    cout << &a << endl;
    cout << &b << endl;
    cout << &c << endl;

    int * p1 = (int*) malloc (4);
    int * p2 = (int*) malloc (4);
    int * p3 = (int*) malloc (4);

    cout << p1 << endl;
    cout << p2 << endl;
    cout << p3 << endl;

    free(p1);
    free(p2);
    free(p3);

    return 0;
}
  • But different CPU architectures may be different

Memory allocation

  • Allocate size bytes of uninitialized storage
cpp 复制代码
void* malloc(size_t size);
  • Allocate 4 bytes and convert the pointer to (int *) explicitly
cpp 复制代码
int * p1 = (int *)malloc (4);
  • Question:
cpp 复制代码
int * p1 = (int *) malloc(3);

pointer-convert.cpp

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    int * pi = new int[2]();
    unsigned char * pc = (unsigned char*)pi;
    pc[1] = 1;
    pc[5] = 2;
    cout << "pi[0] = " << pi[0] << endl;
    cout << "pi[1] = " << pi[1] << endl;

    delete []pi;
    //delete []pc; 
    return 0;
}

Memory deallocation

  • The dynamically allocated memory must be deallocated explicitly
cpp 复制代码
void free(void* ptr);
  • Question:
cpp 复制代码
p = (int *) malloc (4 * sizeof(int));
p = (int *) malloc(8 * sizeof(int));

free(p);

第一次申请的内存丢失了,无法管理也无法销毁

cpp 复制代码
void foo()
{
    int* p = (int *) malloc( sizeof(int));
    return;
} //memory leak

内存泄漏

memory leak.cpp

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

void foo()
{
    int* p = (int *) malloc( sizeof(int));
    return;
} //memory leak

int main()
{
    int * p = NULL;
    
    p = (int *) malloc(4 * sizeof(int));
    // some statements
    p = (int *) malloc(8 * sizeof(int));
    // some statements
    free (p);
    // the first memory will not be freed

    for(int i = 0; i < 1024; i++)
    {
        p = (int *) malloc(1024 * 1024 * 1024);
    }
    printf("End\n");

    return 0;
}

4- Allocate memory: CPP Style

operator new and new[]

  • Operator new is similar with malloc() but with more features

newdelete.cpp

cpp 复制代码
#include <iostream>
using namespace std;

struct Student
{
    char name[4];
    int born;
    bool male; 
};

int main()
{
    //allocate an int, default initializer (do nothing)
    int * p1 = new int; 
    //allocate an int, initialized to 0
    int * p2 =  new int();
    //allocate an int, initialized to 5
    int * p3 =  new int(5); 
    //allocate an int, initialized to 0
    int * p4 =  new int{};//C++11    
    //allocate an int, initialized to 5
    int * p5 =  new int {5};//C++11

    //allocate a Student object, default initializer
    Student * ps1 = new Student;
    //allocate a Student object, initialize the members
    Student * ps2 = new Student {"Yu", 2020, 1}; //C++11

    //allocate 16 int, default initializer (do nothing) 
    int * pa1 = new int[16];
    //allocate 16 int, zero initialized 
    int * pa2 = new int[16]();
    //allocate 16 int, zero initialized 
    int * pa3 = new int[16]{}; //C++11
    //allocate 16 int, the first 3 element are initialized to 1,2,3, the rest 0
    int * pa4 = new int[16]{1,2,3}; //C++11

    //allocate memory for 16 Student objects, default initializer
    Student * psa1 = new Student[16];
    //allocate memory for 16 Student objects, the first two are explicitly initialized
    Student * psa2 = new Student[16]{{"Li", 2000,1}, {"Yu", 2001,1}}; //C++11
    cout << psa2[1].name << endl;
    cout << psa2[1].born << endl;



    return 0;
}

Operator delete and delete[]

  • Destroys object/objects allocated by new and free memory
cpp 复制代码
    //deallocate memory
    delete p1;
    //deallocate memory
    delete ps1;

    //deallocate the memory of the array
    delete pa1;
    //deallocate the memory of the array
    delete []pa2;

    //deallocate the memory of the array, and call the destructor of the first element
    delete psa1;
    //deallocate the memory of the array, and call the destructors of all the elements
    delete []psa2;
相关推荐
李元豪3 小时前
【智鹿空间】c++实现了一个简单的链表数据结构 MyList,其中包含基本的 Get 和 Modify 操作,
数据结构·c++·链表
UestcXiye3 小时前
《TCP/IP网络编程》学习笔记 | Chapter 9:套接字的多种可选项
c++·计算机网络·ip·tcp
一丝晨光4 小时前
编译器、IDE对C/C++新标准的支持
c语言·开发语言·c++·ide·msvc·visual studio·gcc
丶Darling.5 小时前
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
c++·算法·动态规划·记忆化搜索·回溯
奶味少女酱~5 小时前
常用的c++特性-->day02
开发语言·c++·算法
我是哈哈hh6 小时前
专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结
c++·算法·动态规划
_小柏_6 小时前
C/C++基础知识复习(15)
c语言·c++
_oP_i7 小时前
cmake could not find a package configuration file provided by “Microsoft.GSL“
c++
mingshili7 小时前
[python] 如何debug python脚本中C++后端的core dump
c++·python·debug
PaLu-LI8 小时前
ORB-SLAM2源码学习:Frame.cc: Frame::isInFrustum 判断地图点是否在当前帧的视野范围内
c++·人工智能·opencv·学习·算法·ubuntu·计算机视觉