-
如果拷贝构造函数如果传递的参数不是引用类型,则调用拷贝永远不成功,因为如果调用了拷贝构造函数,则必须拷贝它的实参,但是为了拷贝实参,我们又需要调用拷贝构造函数,如此循环。
-
如果想要删除默认构造函数,默认拷贝构造函数,默认赋值运算符,可一直接在声明函数后面加上=delete,但是析构函数最好不要被删除,否则无法释放对象内存。
#include<string> #include<cstring> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<unordered_set> #include<unordered_map> using namespace std; class numbered { public: int a, b, c; numbered() = delete; numbered(int x, int y, int z) :a(x), b(y), c(z) {}; }; signed main() { numbered num1(1, 2, 3); //numbered num2; 默认构造函数被删除无法使用 }
-
shared_ptr的引用计数:
-
由于右值引用只能绑定到临时对象,所以右值引用的对象将要被销毁,而且该对象没有其他变量使用。如果想让一个左值转换为对应的右值引用类型,可以通过std::move函数来调用,右值引用注意一下几点:
-
一旦完成资源的移动,移后原对象处于销毁无害状态,原对象必须不在指向被移动的资源,这些资源所有权已经归属新创建的对象。
-
如果一个函数被noexcept修饰,则如果这个函数抛出异常,则程序无论能否被catch捕获会中断执行,而没有被该关键词修饰的函数则可能被catch捕获然后继续执行catch和catch后面的代码。移动构造函数需要notexcept修饰的原因是,如果在对vector进行push_back重新分配空间时,移动失败的话vector内的元素会发生改变,可能已经不存在,导致程序后面发生错误,拷贝失败的话,vector旧元素并不发生改变,vector原有元素还是会存在的。
-
移动构造函数基本是针对指针进行操作的,移动是将原有的指针指向的位置传递给新的指针,并且将原有的指针置空,拷贝是将原有的指针指向的数据copy一份给新的指针,所以移后原对象基本可以说是报废不可用,所以说不建议对移后原对象进行操作。当然将指针置空还有另一个原因,就是如果两个对象的指针都指向同一个地址,则会导致同一个地址的指针被delete多次导致报错,所以需要将指针置空
-
当一个类既有移动构造函数,又有拷贝构造函数的时候,如果传入的参数是非静态右值,则使用移动构造函数,否则使用拷贝构造函数,如果一个类只有拷贝构造函数,则包括右值在内的所有类型参数使用拷贝构造函数。
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <fstream> #include <array> #include <vector> #include <string> #include <exception> #include <algorithm> #include <deque> #include <numeric> #include <memory> #include <initializer_list> #include <exception> #include <cstring> class StrVec { private: char* str = nullptr; int len = 0; public: StrVec(const char* s) { len = std::strlen(s); str = new char[len + 1]; std::strcpy(str, s); } StrVec(const StrVec& s) { if (s.str != nullptr) { len = s.len; delete str; str = new char[len + 1]; std::strcpy(str, s.str); } } StrVec(StrVec&& s) noexcept { std::cout << "调用移动构造函数" << std::endl; if (s.str != nullptr) { len = s.len; delete str; str = s.str; s.str = nullptr; } } StrVec& operator=(const StrVec& s) { if (this != &s) { delete str; len = s.len; str = new char[len + 1]; std::strcpy(str, s.str); } return *this; } StrVec& operator=(StrVec&& s) noexcept { throw "werwer"; if (this != &s) { delete str; len = s.len; str = s.str; s.str = nullptr; } return *this; } friend std::ostream& operator<<(std::ostream& os, const StrVec& val) { os << val.len << " " << val.str; return os; } }; int main() { //int&& rr1 = 42;//正确:字面常量是右值 int&& rr2 = rr1; 错误不能将一个右值引 用绑定到一个右值引用类型的变量上 //int&& rr3 = std::move(rr1);//可以通过move函数来获取左值上的右值引用 StrVec a = "aaaaa"; StrVec b = "bbbbb"; StrVec c = "ccccc"; StrVec d = "ddddd"; try { std::cout << a << " " << b << " " << c << " " << d << std::endl; b = a; StrVec e = a; std::cout << a << " " << b << " " << c << " " << d << " " << e << std::endl; StrVec f = std::move(b); d = std::move(e); std::cout << a << " " << c << " " << d << " " << " " << f << std::endl; } catch (...) { std::cout << "抛出异常"; } return 0; }
-
-
多个功能类似的函数可以组合成一个函数表,便于调用,但是使用关联容器作为函数表可能无法存入函数类对象,所以引入function函数来出入对象
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<map> struct divide { int operator()(int denomiator, int divisor) { return denomiator / divisor; } divide(int) {}; }; int add(int i, int j) { return i + j; } int main() { auto mod = [](int i, int j) {return i % j; }; std::map<std::string, int(*)(int, int)> binops; binops.insert({ "+",add }); binops.insert({ "%",mod }); //lambda在没有捕获任何变量的情况下赋值为函数指针,而不是函数闭包 //如果在捕获情况下传入则会编译错误 //binops.insert({ "/",divide }); 错误 std::cout << binops["%"](10, 4); return 0; }
2
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<map>
#include<functional>
#include<algorithm>
struct divide
{
int operator()(int denomiator, int divisor)
{
return denomiator / divisor;
}
};
int add(int i, int j) { return i + j; }
int func(int i, int j) { return 2 * i + j; }
int func(int i, int j, int k) { return 3 * i + 2 * j + k; }
int main()
{
auto mod = [](int i, int j) { return i % j; };
std::map<std::string, std::function<int(int, int)>> binops;
binops.insert({ "+",add });
binops.insert({ "/",divide() });
binops.insert({ "-",std::minus<int>() });
binops.insert({ "*",[](int i,int j) {return i * j; } });
binops.insert({ "%",mod });
//binops.insert({ "func",func }); 错误不能直接写重载函数名
binops.insert({ "func",[](int i,int j) {return func(i,j); } });//通过lambda代替
std::ostream_iterator<int> os(std::cout, "\n");
os = binops["+"](10, 5);
os = binops["/"](10, 5);
os = binops["-"](10, 5);
os = binops["*"](10, 5);
os = binops["%"](10, 5);
return 0;
}
15
2
5
50
0