文章目录
待整理
函数的后置const
class TestNode {
public:
string member="B";
string get_member() const{
return this->member;
}
};
int main() {
const TestNode node;
cout << node.get_member() << endl;
}
四大函数
构造函数
类构造函数初始化列表:
使用初始化列表是显式地初始化,否则为赋值
有的时候必须用带有初始化列表的构造函数:
- 成员类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。
- const 成员 或 引用类型的成员。因为 const 对象或引用类型只能初始化,不能对他们赋值。
class NoDefaultConstructor {
public:
int data;
NoDefaultConstructor(int data) : data(data) {
}
};
class ListInitializing {
public:
NoDefaultConstructor noDefaultConstructor;
string &str;
ListInitializing(string str) : noDefaultConstructor(0), str(str) {
}
};
int main() {
string str="1,2,3";
ListInitializing listInitializing(str);
ListInitializing listInitializing2("123");
// string &str="123";
string pre="123";
string &str1=string("pre");
拷贝构造 + 拷贝赋值
拷贝构造 与 拷贝赋值 的出发条件
如果没写,编译器会自动实现一套
如果类里面的成员变量有指针,默认的 拷贝构造 会表现出浅拷贝
只要类带着指针,一定要写出这两种函数:
- copy constructor
- copy assignment operator
String(const String& str);
String& operator=(conat String& str);
default copy会造成【浅拷贝】和【内存泄露】的问题
深拷贝:
兄弟之间互为friend
其他
当前类的其他对象的pivate成员,对于当前类是可见的
s1, s2 在栈空间,p在堆空间,离开scope后p不会释放,并且无法被访问
内存泄露?
不检测自我赋值,可能会凉
new做的3个动作:
- 调用malloc(void* 指针)
- 转型
- 调用构造函数
pass by reference 不加 const 时,遇到临时变量,不能编译通过
In general, any time you need to write your own custom copy constructor, you also need to write a custom assignment operator.
48,写31,如果还给操作系统,写30
没有人调用getInstance
的话,static A a
不会存在,首次调用后存在于全局空间。
- composition
has-a
组合,适配器模式,
deque可以念diQ或带克
- delegation
composition by reference
- inherence
is-a
函数的继承不应该从内存的角度去理解,而应该从调用权的角度去理解
设计模式
单例模式
- 双检锁 + 智能指针
#include <memory>
#include <mutex>
#include <cstdio>
class Singleton {
public:
typedef std::shared_ptr<Singleton> Ptr;
~Singleton() {
printf("destructor\n");
}
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
static Ptr get_instance() {
if (instance_ptr == nullptr) {
std::lock_guard<std::mutex> lk(m_mutex);
if (instance_ptr == nullptr) {
instance_ptr = Ptr(new Singleton);
}
}
return instance_ptr;
}
private:
Singleton() {
printf("constructor\n");
}
static Ptr instance_ptr;
static std::mutex m_mutex;
};
Singleton::Ptr Singleton::instance_ptr = nullptr;
std::mutex Singleton::m_mutex;
int main() {
Singleton::Ptr p = Singleton::get_instance();
}
- 局部静态变量
#include <cstdio>
class Singleton {
public:
~Singleton() {
printf("destructor\n");
}
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
static Singleton &get_instance() {
static Singleton instance;
return instance;
}
private:
Singleton() {
printf("constructor\n");
}
};
int main() {
Singleton &instance1 = Singleton::get_instance();
Singleton &instance2 = Singleton::get_instance();
Singleton &instance3 = Singleton::get_instance();
return 0;
}
所用到的特性是在C++11标准中的Magic Static特性:
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。
这样保证了并发线程在获取静态局部变量的时候一定是初始化过的,所以具有线程安全性。
C++静态变量的生存期 是从声明到程序结束,这也是一种懒汉式。
内存管理
堆栈
scope object == auto object ==
global object可以视为static object
new被分解为3个动作
内存分配的cookie
两个cookie各4B,分配的内存必须以16B为单位进行分配,否则会填充
因为cookie+以16B为单位进行内存分配的原因,
对于double , long long这样的8B,16B相当于2个
对于int, float这样的4B,16B相当于4个,其他以此类推
allocator
- defalloc.h
// Inclusion of this file is DEPRECATED. This is the original HP
// default allocator. It is provided only for backward compatibility.
// This file WILL BE REMOVED in a future release.
//
// DO NOT USE THIS FILE unless you have an old container implementation
// that requires an allocator with the HP-style interface.
//
// Standard-conforming allocators have a very different interface. The
// standard default allocator is declared in the header .
#ifndef DEFALLOC_H
#define DEFALLOC_H
#include <new.h>
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#include <iostream.h>
#include <algobase.h>