1) Circular reference cases and solutions:
#include <iostream>
#include <memory>
using namespace std;
class A;
class B
{
public:
B(){
cout<<"B constructor---"<<endl;}
~B(){
cout<<"B deconstructor----"<<endl;}
std::weak_ptr<A> pA; //如果是std::shared_ptr,则会造成引用计数永远无法归0,资源不会被释放;
};
class A
{
public:
A(){
cout<<"A constructor---------"<<endl;}
~A(){
cout<<"A deconstructor----------------"<<endl;}
std::shared_ptr<B> pB;
};
int main()
{
std::shared_ptr<A> pAA = make_shared<A>();
std::shared_ptr<B> pBB = make_shared<B>();
pAA->pB = pBB;
pBB->pA = pAA;
return 0;
}
2) emplace calls the constructor once, push_back calls the constructor once, and copies once. The test code is as follows:
Therefore: use the emplace member function first.
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
struct SBook
{
public:
SBook() : bookName(""), price(0)
{
std::cout << "default construct: " << bookName << std::endl;
}
SBook(std::string bookName_, int price_) : bookName(bookName_), price(price_)
{
std::cout << "construct: " << bookName << std::endl;
};
SBook(const SBook& rhs) : bookName(rhs.bookName), price(rhs.price)
{
std::cout << "copy construct: " << bookName << std::endl;
}
~SBook()
{
std::cout << "deconstruct: " << bookName << std::endl;
}
bool operator <(const SBook& rhs) const
{
return bookName < rhs.bookName;
}
public:
std::string bookName;
int price;
};
int main(int argc, char *argv[])
{
// 测试vector
vector<SBook> books;
// 预先分配,否则整个vector在容量不够的情况下重新分配内存
books.reserve(100);
std::cout << "test push_back:" << endl;
books.push_back(SBook("C++从入门到放弃", 1));
std::cout << endl;
std::cout << "test emplace_back:" << endl;
books.emplace_back("水浒传", 2);
std::cout << endl;
std::cout << "test emplace_back default:" << endl;
books.emplace_back();
auto& book = books.back();
book.bookName = "红楼梦";
book.price = 5;
std::cout << endl;
std::cout << "test emplace:" << endl;
auto it = books.emplace(books.end());
it->bookName = "西游记";
it->price = 3;
std::cout << endl;
std::cout << "output all books: " << endl;
for_each(books.begin(), books.end(), [](const SBook& book)->void
{
std::cout << book.bookName << endl;
});
std::cout << endl;
// 测试set
set<SBook> bookSet;
std::cout << "test bookSet insert:" << endl;
bookSet.insert(SBook("十万个为什么", 1));
std::cout << endl;
std::cout << "test bookSet emplace:" << endl;
bookSet.emplace("新华字典", 2);
std::cout << endl;
std::cout << "output bookset: " << endl;
for_each(bookSet.begin(), bookSet.end(), [](const SBook&book)->void
{
std::cout << book.bookName << endl;
});
std::cout << endl;
return 0 ;
}
3) Use of unordered_map
#include <iostream>
#include <unordered_map>
using namespace std;
template<class K,class V>
using umap = std::unordered_map<K,V>;
int main(void)
{
umap<string,string> m{
{
"111","bbb"},{
"222","ddd"}};
cout<<m["111"]<<endl; //显示key为"111"的value;
return 0;
}
4) Use the parameters of the template class to automatically generate friend functions; see off Xin Jian and Wang Changling
at Furong Tower. They entered Wu at night in the cold rain and the river, and saw off Chu Shangu in the bright light. Relatives and friends in Luoyang ask each other like a heart filled with ice in a jade pot;
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
template<class T1, class T2>
class AA
{
T1 m_x;
T2 m_y;
public:
AA(const T1 x, const T2 y) : m_x(x), m_y(y) {
}
// 非模板友元:友元函数不是模板函数,而是利用模板类参数生成的函数,只能在类内实现。
// 本质:编译器利用模板参数,帮我们生成了一个友元函数,但是这个函数不是模板函数
friend void show(const AA<T1, T2>& a)
{
cout << "x = " << a.m_x << ", y = " << a.m_y << endl;
}
};
int main(void)
{
AA<int,string> a(44,"abcde");
show(a);
return 0;
}
5) The combined use of template classes and functions (including: ordinary functions, specialized versions of function templates, and generalized versions of function templates)
template classes can be used for function parameters and return values!
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
template<class T1, class T2>
class AA // 模板类AA。
{
public:
T1 m_x;
T2 m_y;
AA(const T1 x, const T2 y) : m_x(x), m_y(y) {
}
void show() const {
cout << "show() x = " << m_x << ", y = " << m_y << endl; }
};
// 采用普通函数,参数和返回值是模板类AA的实例化版本。
AA<int, string> func(AA<int, string>& aa)
{
aa.show();
cout << "调用了func(AA<int, string> &aa)普通函数。\n";
return aa;
}
// 函数模板,参数和返回值是的模板类AA。
template <typename T1,typename T2>
AA<T1, T2> func(AA<T1, T2>& aa)
{
aa.show();
cout << "调用了func(AA<T1, T2> &aa)特化函数。\n";
return aa;
}
// 函数模板,参数和返回值是任意类型。
template <typename T>
T func(T &aa)
{
aa.show();
cout << "调用了func(AA<T> &aa)任意类型泛化函数。\n";
return aa;
}
int main()
{
AA<int, string> aa1(3, "我是一只傻傻鸟。"); //以上三个函数,优先调用普通函数,再次调用特化版本,最后是泛化版本!
func(aa1);
AA<double,string> aa2(3.4,"5555"); //特化版本
func(aa2);
}
6) Example of template class inheriting ordinary class:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
class aa
{
public:
int a_;
aa(int a) :a_(a) {
cout << "调用了AA的构造函数。\n"; }
void func1() {
cout << "调用了func1()函数:m_a=" << a_ << endl;; }
};
template<class T1,class T2>
class bb : public aa
{
public:
T1 x_;
T2 y_;
bb(T1 x,T2 y,int a): aa(a),x_(x),y_(y){
cout << "调用了BB的构造函数"<<endl;}
void func2() const {
cout << "调用了func2()函数:x = " << x_ << ", y = " << y_ << endl; }
};
int main(void)
{
bb<int, string> bb(8, "我是一只傻傻鸟。",3);
bb.func2();
bb.func1();
return 0;
}
Learning knowledge tips:
References are disguises of pointer constants.
Constructors generally have two execution phases: initialization phase and assignment phase;
member pointer operator.* or ->* c++-specific
std::is_same //type extraction related functions
integral US [ˈɪntɪɡrəl] adj complete, n integral
typeid and sizeof usage meaning, there are two ways of writing typeid (int);
typeid (variable name or expression);
7) Anonymous unions are generally written in structures
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
struct st_girl // 定义超女结构体。
{
int no; // 超女编号。
union // 定义匿名共同体udata。
{
int a;
double b;
char c[21];
};
};
int main()
{
st_girl girl;
cout<<sizeof(girl)<<endl;
//输出是32 = 4 + 4 + 24; 空的union占1个字节;那为什么4个呢,因为得字节对齐
return 0;
}
8) How to use the community:
#include <iostream> // 包含头文件。
using namespace std; // 指定缺省的命名空间。
union udata // 定义共同体udata。
{
int a;
double b;
char c[21];
};
int main()
{
udata data;
cout << "sizeof(data)="<< sizeof(data) << endl;
cout << "data.a的地址是:" << (void*) & data.a << endl; //输出地址相同
cout << "data.b的地址是:" << (void*) & data.b << endl;//输出地址相同
cout << "data.c的地址是:" << (void*) & data.c << endl;//输出地址相同
data.b = 30;
cout << "data.a=" << data.a << endl;
cout << "data.b=" << data.b << endl;
cout << "data.c=" << data.c << endl;
}
Output result:
sizeof(data)=24
The address of data.a is: 0x7ffd02aa4860
The address of data.b is: 0x7ffd02aa4860
The address of data.c is: 0x7ffd02aa4860
data.a=0
data.b=30
data.c=