C++指针

指针

指针和数字

从概念上看, 指针和整数是截然不同的类型。

整数是可以执行加、减。。。等运算的数字,而指针是描述的位置。因此,不能简单的将整数赋给指针;

int * pt;

pt = 0xB8000000;  这种是错误的

 

0xB8000000 是组合段偏移地址, 是老师计算机系统中视频内存的, 但这条语句并么有告诉程序, 这个数字是一个地址。所以需要强制类型转换;

int * pt;

pt = (int *) 0xB8000000;

 

使用new来分配内存(变量是存放在栈stack的内存里面, 而new从堆heap或者自由存储free store去分配内存)

指针初始化为变量的地址, 变量是在编译时分配的有名称的内存, 而指针只是为通过名称直接访问的内存提供了一个别名。

指针的真正用武之地在于, 在运行阶段分配未命名的内存以存储值。在这种情况下, 只能通过指针来访问内存。

在c语言中可以用malloc()来分配内存, 在c++中仍然可以这样做,但c++还有更好的方法, new运算符。

 int *pn = new int;

new运算符根据类型来确定需要多少字节。并返回地址。在这里我们说pn指向一个数据对象, 这里的“对象”不是“面向对象编程”中的对象,而是一样东西。 术语“数据对象”比“变量” 更通用, 它指的是

为数据项分配的内存块。,因此pn指向的是内存

#include <iostream>


int main(int argc, char const *argv[]) {


  using namespace std;
  int i = 10;
  int * p = new int;
  int * b = &i;
  std::cout << "p:" << p << '\n';
  *p = 1001;
  std::cout << "p:" << p << '\n';

  std::cout << "*p:" << *p << '\n';
  delete p;
  // delete p; //not ok now
  // delete b;  // not ok now


  return 0;
};

 

 

 

那么我们要来思考一个问题, 就是内存被耗尽, 计算机可能没有足够的内存而无法满足new请求, 这种情况会引发异常。

 

使用new创建动态数组

对于小型数据对象来说,声明一个变量, 比使用new和指针更简单。但对于大型数据(如数组,字符串和结构), 应使用new, 这正是new的用武之地。

同时|:

1.静态联编:如果通过声明来创建数组, 在编译时给数组分配内存被被称为静态联编
2. 动态联编:使用new时, 运行阶段需要数组, 则创建它, 不需要,就不创建, 还可以选择长度, 被称为动态联编。

 

#include <iostream>


int main(int argc, char const *argv[]) {


  using namespace std;
  int * i = new int [3];
  std::cout << "i:" << i << '\n';
  i[0] = 0;
  i[1] = 1;
  i[2] = 2;
  std::cout << "i[0]:" << i[0] << '\n';
  std::cout << "i[1]:" << i[1] << '\n';
  std::cout << "i[2]:" << i[2] << '\n';

  i += 1;  // 所以这种操作是错误的
  std::cout << "i" << i << '\n';
  std::cout << "i[0]:" << i[0] << '\n';
  std::cout << "i[1]:" << i[1] << '\n';
  std::cout << "i[2]:" << i[2] << '\n';
  delete [] i;


  return 0;
}

 

但是为撒子delete了以后就错了, 由于i是new出来的, 在堆里面, 越界操作就是野指针,所以delete的时候找不到,系统会报错。

 

使用delete释放内存

 

 C++的魅力之一就是使用new请求来内存管理。另一方面就是使用delete, 那么delete用法:

int * pt = new int;
short * ps = new short [500];

delete pt;
delete [] ps;

 

 需要遵守的规则:

1. 不要使用delete来释放不是new分配的内存

 2. 不要使用delete释放同一内存块2次

3. 如果使用new【】为数组分配内存, 则应使用delete【】释放。

4. 如果使用new为一个实体分配内存, 则应使用delete(没有方括号)来释放。

5.对空指针应用delete是安全的

 指针代码块

int -- float

#include <iostream>
#include <cstring>

// int
/*
int main(int argc, char const *argv[]) {
  using namespace std;
  int b=12;
  int * a = &b;
  int * c;
  c = &b;
  std::cout << c << ";" << a << '\n';
  std::cout << *c << '\n';
  std::cout << *a << '\n';
  return 0;
}
*/

/*
int main(int argc, char const *argv[]) {
  int * b = (int *)11;
  std::cout << b << '\n';

  int *p = new int;
  *p = 1001;
  std::cout << *p << '\n';
  delete p;
  return 0;
}
*/

 

 

char

// str
/*
int main(int argc, char const *argv[]) {
  using namespace std;

  char a[] = "abc";
  char * b = a;
  std::cout << b << '\n';

  char * c = new char[strlen(a) + 1];
  c = a;
  std::cout << a << '\n';
  delete [] c;
  return 0;
}
*/

 

list

// list
/*
int main(int argc, char const *argv[]) {

  using namespace std;

  int a[] = {1,2,3};
  int b[2][2] = {{1, 2}, {3, 4}};
  // int * p = b;
  int * p = b[0];
  std::cout << *(p) << '\n';

  int * c = new int[3];
  c[0] = 3;
  std::cout << c[0] << '\n';
  delete [] c;
  return 0;
}
*/

 

 

struct

// struct

#include <iostream>
#include <string.h>

using namespace std;

struct abc{
  char name[10];
  float volume;
  int b;
};

 

int main(int argc, char const *argv[]){
  abc ps;
  ps.volume = 20.00;
  memcpy(ps.name, "hello", 6);
  printf("%s\n", ps.name);

  abc *pp = new abc;
  pp->b = 222;
  printf("%d\n", pp->b);

  return 0;
}

 

 

对象指针写法

// 目录和文件都小写, 重要的事情才大写

// 类的名字首字母大写
#include <iostream>
#include <string>

using namespace std;


class Person {
private:
    int _pid;
    string _name;
    int _age;

public:
    int testAbc = 123;
    int testAbd = 124;

    Person();

    ~Person();

    void setpid(int pid);

    int getpid();

    void setname(string name);

    string getname();

    void setage(int age);

    int getage();
};

Person::Person() {
    std::cout << "构造函数: " << this->testAbc << '\n';
}

Person::~Person() {
    std::cout << "析构函数: " << this->testAbd << '\n';
}


void Person::setpid(int pid) {
    this->_pid = pid; // this 表示当前对象下的_pid
}

int Person::getpid() {
    return this->_pid;
}

void Person::setname(string name) {
    this->_name = name;
}

string Person::getname() {
    return _name;
}

void Person::setage(int age) {
    this->_age = age;
}

int Person::getage() {
    return _age;
}

int main() {
// 锦绣城, 双滦区 2区观鱼园
// -----普通方式----- //
/*
Person per;
per.setpid(1);
per.setname("tom");
per.setage(20);

int pid = per.getpid();
string name = per.getname();
int age = per.getage();

std::cout << "pid: " << pid << " ";
std::cout << "name: " << name<< " ";
std::cout << "age: " << age << '\n';
*/

// -----指针方式-----//
    Person *per = new Person();
    per->setpid(1);
    per->setname("Baker");
    per->setage(20);
    delete per;


    return 0;
}

 

posted @ 2017-08-15 14:00  我当道士那儿些年  阅读(202)  评论(0编辑  收藏  举报