C/C++教程

C++学习笔记 2

本文主要是介绍C++学习笔记 2,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

C++学习笔记2

面向对象

含指针的类string

data怎么存?

用指针不错,总不能一个个保存吧

拷贝构造、拷贝复制

构造函数接受的参数是自己这个类的对象(引用),为拷贝构造。

=重载,参数是自己这个类的对象,为拷贝复制。

String(const String& str);                    
String& operator=(const String& str); 

inline
String::String(const String& str)
{
   m_data = new char[ strlen(str.m_data) + 1 ];
   strcpy(m_data, str.m_data);
}

inline
String& String::operator=(const String& str)
{
   if (this == &str)
      return *this;//检测自我赋值,一定要

   delete[] m_data;//先清空
   m_data = new char[ strlen(str.m_data) + 1 ];//分配一样的空间
   strcpy(m_data, str.m_data);//拷贝
   return *this;
}

String s1("hello");
String s2(s1);
String s2=s1;//与上一行一个意思,看函数实现也差不多

只要写的是带指针的类,就必须完成这两个函数。对于不带指针的类complex,不写也一样,编译器会忠实的完全bit复制过来,已经很好了。但是指针不能复制,空间应该重新分配。

浅拷贝就是纯bit复制,造成内存泄露和别名alias;深拷贝就是把指针指的内容重新创建并赋值。

这里的构造函数,拿到外部去实现了。

构造函数

String(const char* cstr=0);

#include <cstring>
inline
String::String(const char* cstr)
{
   if (cstr) {
      m_data = new char[strlen(cstr)+1];
      strcpy(m_data, cstr);
   }
   else {   //未指定初值
      m_data = new char[1];
      *m_data = '\0';
   }
}

String* p=new String(“hello”)

析构函数

写法类似构造函数,与类同名,且前方有个 ~.

~String();


inline
String::~String()
{
   delete[] m_data;
}

当这个类的对象死亡时、离开作用域时,会被调用(自动)。

有指针的类,要做析构函数处理动态分配的空间(手动)。

用指针动态分配的对象,也要手动delete。

输出函数

要写成全局函数,

#include <iostream>
using namespace std;

ostream& operator<<(ostream& os, const String& str)
{
   os << str.get_c_str();
   return os;
}

char* get_c_str() const {return m_data;}//写到类里面

堆Heap和栈Stack,与new关键字

内存

栈是存在于一个函数作用域的一块内存空间,用于存放参数、返回地址等。

堆是由操作系统提供的一块全局内存空间,程序可以动态分配从其中获得一定的大小。

Complex c1(1,2);
Complex* c2=new Complex(2,3);

栈里的内容,函数结束后(离开作用域)就会被释放。会调用析构函数。又称为 auto object,因为会自动释放。

如果是 static object,直到整个程序结束后才会释放。

如果是 global object,有点类似static,也是程序结束才会释放。

堆里的内容,必须手动释放。一个new对应一个delete,其生命在delete后结束。如果不释放,会内存泄露,其严重性在于:当作用域结束后,指针的生命结束了,作用域之外没办法使用指针,对这一块的内存就失去了控制。

new与delete

new是先分配memory,再调用构造函数ctor。可以分为下述步骤:

Complex* pc=new Complex(1,2);

Complex* pc;
void mem=operator new(sizeof(Complex));//operator new其实是一个名字特别的函数,下一层就是malloc。
pc=static_cast<Complex*>(mem);//指针的类型转换
pc->Complex::Complex(1,2);//构造函数

构造函数是个成员函数,现在是由指针调用,因此相当于指针是构造函数里的 this,指向内存空间的起点。然后调用构造函数复制。

delete是先调用析构函数的dtor,再释放memory。

String* ps = new String("Hello");
delete ps;


String::~String(ps);//释放字符串里面的动态分配的空间
operator delete(ps);//下一层是free

内存块大小

vc给分配的内存空间一定是16B的倍数。

在debug下。会包含很多调试信息,以及cookie(用于记录长度和分配状况,提供给malloc和free用)。还可能有补充为16B整数倍的padding。

在release下,没有调试信息,别的一样。

有中括号的new和delete (array new/delete)

要互相搭配,否则会出错。写法如下:

m_data = new char[strlen(cstr)+1];

delete[] m_data;

动态分配的数组中,在数据前会有一个整数记录数组容量。(VC)具体问题如下:

image-20220110213647651

删除整个数组没问题,因为大小写在cookie里;但是除了第0个元素,后面的元素的没有调用析构函数,这就造成了内存泄露。(当然是因为后面类的变量有指针)

这篇关于C++学习笔记 2的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!