> 文章列表 > MyString 类 构造函数 对象行为 设计模式 单例模式

MyString 类 构造函数 对象行为 设计模式 单例模式

MyString 类 构造函数 对象行为 设计模式 单例模式

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、MyString类
      • 错误的 <font color = blue>
        • 正确的
  • 二、构造函数的各种重载形式
  • 三、多线程下的对象行为
  • 单例模式
    • 1. 懒汉式
    • 2. 饿汉式
    • 总结
  • 总结

前言

记录不同行为的拷贝与构造情况。


一、MyString类

错误的

class MyString
{
private:char* chs;
public:MyString():chs(nullptr){std::cout << "默认构造 MyString(),thread_id: " << std::this_thread::get_id() << std::endl;}MyString(const char* s){chs = new char[strlen(s)+1];memcpy(chs, s, strlen(s)+1);std::cout << "重载构造 MyString(const char* s),thread_id: " << std::this_thread::get_id() << std::endl;}virtual ~MyString(){if(chs) {delete[] chs;chs = nullptr;}std::cout << "析构 ~MyString(),thread_id: " << std::this_thread::get_id() << std::endl;}MyString(const MyString& str){if(chs){delete[] chs;}chs = new char[strlen(str.chs)+1];memcpy(chs, str.chs, strlen(str.chs)+1);std::cout << "拷贝构造 MyString(const MyString&),thread_id: " << std::this_thread::get_id() << std::endl;}MyString& operator=(const MyString& str){if (&str == this)return *this;if(chs){delete[] chs;}chs = new char[strlen(str.chs)+1];memcpy(chs, str.chs, strlen(str.chs)+1);std::cout << "赋值 operator=,thread_id: " << std::this_thread::get_id() << std::endl;}void operator()(){std::cout << "函数对象 operator()(),thread_id: " << std::this_thread::get_id() << std::endl;}void memberfn(){std::cout << "成员函数 memberfn,thread_id: " << std::this_thread::get_id() << std::endl;}
};

正确的

#include <iostream>
#include <new>
#include <memory>
#include <thread>
#include <string.h>class MyString
{
public:char* chs;
public:MyString(){chs = new char[1];*chs = '\\0';std::cout << "默认构造 MyString() | this = "<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;}MyString(const char* s){chs = new char[strlen(s)+1];memcpy(chs, s, strlen(s)+1);std::cout << "重载构造 MyString(const char* s) | this = "<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;}
/*    MyString(const MyString&& str): MyString(str){;} */~MyString(){delete[] chs;std::cout << "析构 ~MyString() | this = "<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;}MyString(const MyString& str){chs = new char[strlen(str.chs)+1];memcpy(chs, str.chs, strlen(str.chs)+1);std::cout << "拷贝构造 MyString(const MyString&) | this = "<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;}MyString& operator=(const MyString& str){std::cout << "赋值 operator= | this = "<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;if (&str == this)return *this;delete[] chs;chs = new char[strlen(str.chs)+1];memcpy(chs, str.chs, strlen(str.chs)+1);return *this;}void operator()(){std::cout << "函数对象 operator()() | this = "<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;}void memberfn(){std::cout << "成员函数 memberfn | this = "\\<< this << " | thread_id: " << std::this_thread::get_id() << std::endl;}
};

二、构造函数的各种重载形式

编译器根据实例化对象时传入的参数类型选择对应形式的构造函数

MyString();
MyString(const char*);
MyString(const MyString&);

根据一个已存在的对象初始化新对象时调用拷贝构造
如函数,MyString fun(MyString str); 在传递参数和函数返回时调用拷贝构造

MyString s1;       // 默认构造
MyString s2 = s1;  // 拷贝构造

operator=的安全定义参见:https://blog.csdn.net/surfaceyan/article/details/125586372

三、多线程下的对象行为

非静态成员函数

    MyString s1;// MyString s2 = s1;std::thread thd(&MyString::memberfn, &s1);  // non-static 成员函数必须带&, 非静态成员函数的第一个参数为 decltype(this)thd.join();
默认构造 MyString() | this = 0x7fffb8746b68 | thread_id: 140645677708224
成员函数 memberfn   | this = 0x7fffb8746b68 | thread_id: 140645670843968
析构 ~MyString()   | this = 0x7fffb8746b68 | thread_id: 140645677708224

单例模式

1. 懒汉式

// 1)静态指针+用到时初始化  2)局部静态变量
/// @brief 延时加载,如配置文件,当用到时才实例化对象
// 在单线程中,这样的写法是可以正确使用的,但是在多线程中就不行了,该方法是线程不安全的。
class SingleTon
{
private:SingleTon(/* args */) = default;~SingleTon() = default;
public:SingleTon(const SingleTon&) = delete;SingleTon& operator=(const SingleTon&) = delete;static SingleTon& GetInstance(){if (!value_) {value_ = new SingleTon();}return *value_;}
private:static SingleTon* value_;
public:int a = 0;
};
SingleTon* SingleTon::value_ = nullptr;
/// @brief 线程不安全
class SingleTon2
{
public:SingleTon2(const SingleTon2&) = delete;SingleTon2& operator=(const SingleTon2&) = delete;static SingleTon2& GetInstance(){static SingleTon2 value;return value;}
private:SingleTon2(/* args */) = default;~SingleTon2() = default;
};

2. 饿汉式

// 1)直接定义静态对象  
// 线程安全
class SingleTon3
{
public:SingleTon3(const SingleTon3&) = delete;SingleTon3& operator=(const SingleTon3&) = delete;static SingleTon3& GetInstance(){return instance;}
private:static SingleTon3 instance;SingleTon3(/* args */) = default;~SingleTon3() = default;
};
SingleTon3 SingleTon3::instance;  // instance = SingleTon3()// 2)静态指针+类外初始化时new空间实现
class SingleTon4
{
public:SingleTon4(const SingleTon4&) = delete;SingleTon4& operator=(const SingleTon4&) = delete;static SingleTon4& GetInstance(){return *instance_ptr;}
private:static SingleTon4* instance_ptr;SingleTon4() = default;~SingleTon4() = default;
};
SingleTon4* SingleTon4::instance_ptr = new SingleTon4();

总结

静态的对象或者静态的指针,类内创建或类外创建


总结