实现一个string类
代码如下
#include <iostream>
#include <string.h>
using namespace std;
class myString{
public:
//构造函数
myString(const char* str = NULL);
//拷贝构造函数
myString(const myString& str);
//赋值操作
myString& operator=(const myString& str);
~myString();
void show();
private:
char* m_data;
};
myString::myString(const char* str) {
if (str == NULL) {
m_data = new char[1];
if (m_data == nullptr) {
cout << "memory allocate failed!" << endl;
exit(1);
}
m_data[0] = '\0';
} else {
m_data = new char[strlen(str) + 1];
if (m_data == nullptr) {
cout << "memory allocate failed!" << endl;
exit(1);
}
strcpy(m_data, str);
}
}
myString::myString(const myString& str) {
m_data = new char[strlen(str.m_data) + 1];
if (m_data == nullptr) {
cout << "memory allocate failed!" << endl;
exit(1);
}
strcpy(m_data, str.m_data);
}
myString& myString::operator=(const myString& str) {
if (this == &str) return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
if (m_data == nullptr) {
cout << "memory allocate failed!" << endl;
exit(1);
}
strcpy(m_data, str.m_data);
return *this;
}
myString::~myString() {
delete[] m_data;
}
void myString::show() {
cout << m_data << endl;
}
int main() {
myString a;
myString c("asdf");
myString b(c);
a = c;
a.show();
b.show();
c.show();
return 0;
}
考察的点
对于类的构造函数,赋值拷贝函数的考察
为什么需要拷贝构造函数?
这里就涉及到一个深、浅拷贝的问题了。
首先来看下拷贝构造函数是干什么用的。
拷⻉构造函数的函数参数为对象本身的引⽤,⽤于根据⼀个已存在的对象复制 出⼀个新的该类的对象,⼀般在函数中会将已存在的对象的数据成员的值⼀⼀复制到新创建的 对象中。
如果没有自己定义拷⻉构造函数,则系统会默认创建⼀个拷⻉构造函数,但当类中有 指针成员时,最好不要使⽤编译器提供的默认的拷⻉构造函数,最好⾃⼰定义并且在函数中执 ⾏深拷⻉。
我们可以通过上面给出的例子来看
int main() {
myString a;
myString c("asdf");
myString b(c);
a = c;
a.show();
b.show();
c.show();
return 0;
}
在main函数中初始化了三个对象,其中a调用默认构造函数,c也是(自己调试一下就知道了),而b却是使用拷贝构造函数
如果在拷贝构造函数中并不是单纯的复制指针的值,而是重新分配一片内存。内存地址如下:
这里的b,c的m_data指向的是不同的内存地址并且都相差0x20 即32个bit即4个字节
这样的话在析构函数(如下):delete是不会出现问题的。内存是正常的释放的。
myString::~myString() {
delete[] m_data;
}
但是如果不使用系统默认的拷贝构造函数的话:
这里就会发现b和c的m_data指向了同一片内存地址,这样的话在执行析构函数的时候就会对同一个地址delete两次。导致野指针的问题。
链表相关
单链表
企业一般不会考察静态链表
代码:
struct pNode
{
int data;
pNode *next;
pNode(int _data):data(_data), next(NULL){}
/* data */
}*head;
void addpHead(int val) {
pNode *p = new pNode(val);
p->next = head->next;
head->next = p;
}
//删除p后面的节点,即p->left
void premove(pNode *p) {
pNode *tmp = p->next;
p->next = p->next->next;
delete tmp;
}
双链表
struct tNode
{
int key, val;
tNode *left, *right;
tNode(int _key, int _val):key(_key), val(_val), left(NULL), right(NULL) {}
/* data */
}*L, *R;
//删除p节点,不需要知道之前的节点
void tremove(tNode *p) {
p->right->left = p->left;
p->left->right = p->right;
}
//在左节点插入
void Linsert(tNode *p) {
p->right = L->right;
p->left = L;
L->right->left = p;
L->right = p;
}
//在右端点插入
void Rinsert(tNode *p) {
p->left = R->left;
p->right = R;
R->left->right = p;
R->left = p;
}
智能指针
代码如下:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
template <typename T>
class SharedPtr{
private:
T *m_ptr_; //内部指针,保证拷贝指向同一内存
size_t *m_count_;
public:
//构造函数
SharedPtr() : m_ptr_(nullptr), m_count_(new size_t) {}
SharedPtr(T *p) : m_ptr_(p), m_count_(new size_t){
if (p == nullptr) {
m_count_ = 0;
} else {
m_count_ = 1;
}
}
//析构函数
~SharedPtr() {
if (this->m_ptr_) {
if (--(*m_count_) == 0) {
delete m_count_;
delete m_ptr_;
m_count_ = nullptr;
m_ptr_ = nullptr;
}
}
}
//拷贝赋值函数
SharedPtr(const SharedPtr& ptr) {
if (this != ptr) {
this->m_ptr_ = ptr.m_ptr_;
this->m_count_ = ptr.m_count_;
(*this->m_count_) ++;
}
}
//赋值拷贝重载=
SharedPtr &operator=(const SharedPtr& ptr) {
//防止自我赋值
if (this->m_ptr_ == ptr.m_ptr_) {
return *this;
}
if (this->m_ptr_) {
if (--(*this->m_count_) == 0) {
delete m_count_;
delete m_ptr_;
m_count_ = nullptr;
m_ptr_ = nullptr;
}
}
m_ptr_ = ptr.m_ptr_;
m_count_ = ptr.m_count_;
(*m_count_)++;
return *this;
}
//移动构造函数
SharedPtr(SharedPtr&& ptr) {
m_ptr_ = ptr.m_ptr_;
m_count_ = ptr.m_count_;
++(*m_count_);
}
//移动赋值运算
void operator=(SharedPtr&& ptr) {
SharedPtr(std::move(ptr));
}
//重载->
T& operator->() {
if (this->m_ptr_) return this->m_ptr_;
}
//重载*
T& operator*() {
if (this->m_ptr_) return *(this->m_ptr_);
}
//返回用户个数
size_t use_count() {
return *(this->m_count_);
}
};
void Std_shared_ptr_test() {
shared_ptr<int>ptr(new int);
shared_ptr<int>ptr2(ptr);
shared_ptr<int> ptr3;
ptr3 = ptr2;
cout << "这是std::shared_ptr测试结果:" << endl;
cout <<"ptr.use_count:"<<ptr.use_count() << endl;
cout <<"ptr2.use_count:"<< ptr2.use_count() << endl;
cout <<"ptr3.use_count:"<< ptr3.use_count() << endl;
*ptr3 = 100;
cout << "通过对*ptr3赋值 取ptr的值为:"<<*ptr << endl;
cout << endl;
}
void Shared_ptr_Test() {
SharedPtr<int>ptr(new int);
SharedPtr<int>ptr2(ptr);
SharedPtr<int>ptr3;
ptr3 = ptr2;
cout << "这是std::shared_ptr测试结果:" << endl;
cout <<"ptr.use_count:"<<ptr.use_count() << endl;
cout <<"ptr2.use_count:"<< ptr2.use_count() << endl;
cout <<"ptr3.use_count:"<< ptr3.use_count() << endl;
*ptr3 = 100;
cout << "通过对*ptr3赋值 取ptr的值为:"<<*ptr << endl;
cout << endl;
}
int main() {
// std::string s = "hello world";
// auto left = std::move(s);
// std::cout << left << std::endl;
// std::cout << s << std::endl;
Shared_ptr_Test();
Std_shared_ptr_test();
return 0;
}
shared_ptr实现共享式拥有概念,多个智能指针可以指向相同对象,该对象和其相关资源会在最后一个引用被销毁时候释放
使用计数机制来表明资源被几个指针共享。