您现在的位置是:首页 >技术交流 >MyString 类 构造函数 对象行为 设计模式 单例模式网站首页技术交流
MyString 类 构造函数 对象行为 设计模式 单例模式
简介MyString 类 构造函数 对象行为 设计模式 单例模式
系列文章目录
文章目录
前言
记录不同行为的拷贝与构造情况。
一、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 = '';
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();
总结
静态的对象或者静态的指针,类内创建或类外创建
总结
略
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。