struct A {
int i,j;
A(int m,int n):i(m),j(n) { }
};
A func(int m,int n )
{
return {m,n};
}
int main()
{
int arr[3]{1, 2, 3};
vector<int> iv{1, 2, 3};
map<int, string> mp{{1, "a"}, {2, "b"}};
string str{"Hello World"};
int * p = new int[20]{1,2,3};
A * pa = new A {3,7};
return 0;
}
#include "iostream"
using namespace std;
class B {
public:
int m = 1234;
int n;
};
int main() {
B b;
cout << b.m << endl; //输出 1234
return 0;
}
用于定义变量,编译起可以自动判断变量的类型
class A{};
int main() {
auto i = 100; // i 是 int
auto p = new A(); // p 是 A *
auto k = 34343LL; // k 是 long long
map<string,int,greater<string> > mp;
mp.insert(pair<string,int>("21321",20));
for( auto i = mp.begin(); i != mp.end(); ++i)
//i的类型是: map >::iterator
cout << i->first << "," << i->second ;
return 0;
}
class A {
};
A operator+(int n, const A &a) {
return a;
}
template<class T1, class T2>
auto add(T1 x, T2 y) -> decltype(x + y) {
return x + y;
}
int main() {
auto d = add(100, 1.5); // d是double d=101.5
auto k = add(100, A()); // d是A类型
cout << d << endl;
return 0;
}
求表达式的类型
int i;
double t;
struct A { double x; };
const A* a = new A();
decltype(a) x1; // x1 is A *
decltype(i) x2; // x2 is int
decltype(a->x) x3; // x3 is double
decltype((a->x)) x4 = t; // x4 is double&
shared_ptr ptr(new T);
// T 可以是 int ,char, 类名等各种类型#include "memory"
struct A {
int n;
A(int v = 0) : n(v) {}
~A() { cout << n << " destructor" << endl; }
};
int main() {
shared_ptr<A> sp1(new A(2)); //sp1托管A(2)
shared_ptr<A> sp2(sp1); //sp2也托管 A(2)
cout << "1)" << sp1->n << "," << sp2->n << endl;//输出1)2,2
shared_ptr<A> sp3;
A *p = sp1.get(); //p 指向 A(2)
cout << "2)" << p->n << endl;
sp3 = sp1; //sp3也托管 A(2)
cout << "3)" << (*sp3).n << endl; //输出 2
sp1.reset(); //sp1放弃托管 A(2)
if (!sp1)
cout << sp1 << endl;
cout << "4)sp1 is null" << endl; //会输出
A *q = new A(3);
sp1.reset(q); // sp1托管q
cout << "5)" << sp1->n << endl; //输出 3
shared_ptr<A> sp4(sp1); //sp4托管A(3)
shared_ptr<A> sp5;
sp1.reset(); //sp1放弃托管 A(3)
cout << "before end main" << endl;
sp4.reset(); //sp1放弃托管 A(3)
cout << "end main" << endl;
return 0; //程序结束,会delete 掉A(2)
}
1)2,2
2)2
3)2
0
4)sp1 is null
5)3
before end main
3 destructor
end main
2 destructor
#include
#include
using namespace std;
int main() {
int *p1 = NULL;
int *p2 = nullptr;
shared_ptr<double> p3 = nullptr;
if (p1 == p2)
cout << "equal 1" << endl;
if (p3 == nullptr)
cout << "equal 2" << endl;
// if (p3 == p2); // error
if (p3 == NULL)
cout << "equal 4" << endl;
// bool b = nullptr; // b = false
// int i = nullptr; //error,nullptr不能自动转换成整型
return 0;
}
equal 1
equal 2
equal 4
#include
#include
using namespace std;
struct A {
int n;
A(int i) : n(i) {}
};
int main() {
int ary[] = {1, 2, 3, 4, 5};
for (int &e: ary)
e *= 10;
for (int e: ary)
cout << e << ",";
cout << endl;
vector<A> st(ary, ary + 5);
for (auto &it: st)
it.n *= 10;
for (A it: st)
cout << it.n << ",";
return 0;
}
10,20,30,40,50,
100,200,300,400,500,
右值:一般来说,不能取地址的表达式,就是右值,能取地址的,就是左值
class A { };
A & r = A(); // error , A()是无名变量,是右值
A && r = A(); //ok, r 是右值引用
主要目的是提高程序运行的效率,减少需要进行深拷贝的对象进行深拷贝的次数。
#include
#include
#include
using namespace std;
class String {
public:
char *str;
String() : str(new char[1]) { str[0] = 0; }
String(const char *s) {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
String(const String &s) {
cout << "copy constructor called" << endl;
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
}
String &operator=(const String &s) {
cout << "copy operator= called" << endl;
if (str != s.str) {
delete[] str;
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
}
return *this;
}
// move constructor
String(String &&s) : str(s.str) {
cout << "move constructor called" << endl;
s.str = new char[1];
s.str[0] = 0;
}
// move assigment
String &operator=(String &&s) {
cout << "move operator= called" << endl;
if (str != s.str) {
delete[] str;
str = s.str;
s.str = new char[1];
s.str[0] = 0;
}
return *this;
}
~String() { delete[] str; }
};
template<class T>
void MoveSwap(T &a, T &b) {
T tmp(move(a)); // std::move(a)为右值,这里会调用move constructor
a = move(b); // move(b)为右值,因此这里会调用move assigment
b = move(tmp); // move(tmp)为右值,因此这里会调用move assigment
}
int main() {
//String & r = String("this"); // error
String s;
s = String("ok"); // String("ok")是右值
cout << "******" << endl;
String &&r = String("this");
cout << r.str << endl;
String s1 = "hello", s2 = "world";
MoveSwap(s1, s2);
cout << s2.str << endl;
return 0;
}
move operator= called
******
this
move constructor called
move operator= called
move operator= called
hello
函数返回值为对象时,返回值对象如何初始化?
struct A {
A(const A &a) = delete;
A(const A &&a) { cout << "move" << endl; }
A() {};
};
A b;
A func() {
A a;
return a;
}
void func2(A a) {}
int main() {
A a1;
// A a2(a1); //compile error
// func2(a1); //compile error
func();
return 0;
}
哈希表插入和查询的时间复杂度几乎是常数
#include
using namespace std;
int main() {
unordered_map<string, int> turingWinner; //图灵奖获奖名单
turingWinner.insert(make_pair("Dijkstra", 1972));
turingWinner.insert(make_pair("Scott", 1976));
turingWinner.insert(make_pair("Wilkes", 1967));
turingWinner.insert(make_pair("Hamming", 1968));
turingWinner["Ritchie"] = 1983;
string name;
cin >> name; //输入姓名
unordered_map<string, int>::iterator p =
turingWinner.find(name);
//据姓名查获奖时间
if (p != turingWinner.end())
cout << p->second;
else
cout << "Not Found" << endl;
return 0;
}
#include
#include //使用正则表达式须包含此文件
using namespace std;
int main() {
regex reg("b.?p.*k");
cout << regex_match("bopggk", reg) << endl;//输出 1, 表示匹配成功
cout << regex_match("boopgggk", reg) << endl;//输出 0, 匹配失败
cout << regex_match("b pk", reg) << endl; //输出 1, 表示匹配成功
regex reg2("\\d{3}([a-zA-Z]+).(\\d{2}|N/A)\\s\\1");
string correct = "123Hello N/A Hello";
string incorrect = "123Hello 12 hello";
cout << regex_match(correct, reg2) << endl; //输出 1,匹配成功
cout << regex_match(incorrect, reg2) << endl; //输出 0, 失败
}
1
0
1
1
0
[外部变量访问方式说明符](参数表) ->返回值类型
{
语句组
}
[] 不使用任何外部变量
[=] 以传值的形式使用所有外部变量
[&] 以引用形式使用所有外部变量
[x, &y] x 以传值形式使用,y 以引用形式使用
[=,&x,&y] x,y 以引用形式使用,其余变量以传值形式使用
[&,x,y] x,y 以传值的形式使用,其余变量以引用形式使用
“->返回值类型”也可以没有, 没有则编译器自动判断返回值类型。
int main()
{
int x = 100,y=200,z=300;
cout << [ ](double a,double b) { return a + b; }(1.2,2.5)<< endl;
auto ff = [=,&y,&z](int n) {
cout <<x << endl;
y++; z++;
return n*n;
};
cout << ff(15) << endl;
cout << y << "," << z << endl;
int a[4] = { 4,2,11,33};
sort(a,a+4,[ ](int x,int y)->bool {
return x%10 < y%10; });
for_each(a,a+4,[ ](int x) {cout << x << " " ;} ) ;
}
3.7
100
225
201,301
11 2 33 4
实现递归求斐波那契数列第n项:
#include
int main(){
// function 表示返回值为 int, 有一个int参数的函数
function<int(int)> fib = [&fib](int n){
return n <=2 ? 1 : fib(n-1) +fib(n-2);
};
cout << fib(5) << endl;
cout << fib(3) << endl;
cout << fib(10) << endl;
return 0;
}
#include "thread"
struct MyThread{
void operator()(){
while (true)
cout << "IN MYTHREAD\n";
}
};
void my_thread(int x){
while (x)
cout << "in my_thread\n";
};
int main(){
MyThread x; // 对x 的要求:可复制
thread th(x); // 创建线程并执行
thread th1(my_thread,10);
while (true)
cout << "in main\n";
return 0;
}
static_cast、interpret_cast、const_cast和dynamic_cast
#include
using namespace std;
class A
{
public:
operator int() { return 1; }
operator char * (){ return NULL; }
};
int main()
{
A a;
int n;
char * p = "New Dragon Inn";
n = static_cast<int>(3.14); // n 的值变为 3
n = static_cast<int>(a); //调用a.operator int, n的值变为 1
p = static_cast<char*>(a);
//调用a.operator int *,p的值变为 NULL
// n = static_cast (p);
//编译错误,static_cast不能将指针转换成整型
// p = static_cast(n);
//编译错误,static_cast不能将整型转换成指针
return 0;
}
reinterpret_cast用来进行各种不同类型的指针之间的转换、不同类型的引用之间转换、以及指针和能容纳得下指针的整数类型之间的转换。转换的时候,执行的是逐个比特拷贝的操作。
class A {
public:
int i;
int j;
A(int n) : i(n), j(n) {}
};
int main() {
A a(100);
int &r = reinterpret_cast<int &>(a); //强行让 r 引用 a
r = 200; //把 a.i 变成了 200
cout << a.i << "," << a.j << endl; // 输出 200,100
int n = 300;
A *pa = reinterpret_cast<A *> ( &n); //强行让 pa 指向 n
pa->i = 400; // n 变成 400
pa->j = 500; //此条语句不安全,很可能导致程序崩溃
cout << n << endl; // 输出 400
typedef void (*PF1)(int);
typedef int (*PF2)(int, char *);
PF1 pf1;
PF2 pf2;
pf2 = reinterpret_cast<PF2>(pf1); //两个不同类型的函数指针之间可以互相转换
}
200,100
400
用来进行去除const属性的转换。将const引用转换成同类型的非const引用,将const指针转换为同类型的非const指针时用它
int main(){
const string s = "Inception";
string & p = const_cast<string&>(s);
string * ps = const_cast<string*>(&s);// &s的类型是const string *
cout << p <<endl;
cout << *ps <<endl;
return 0;
}
class Base { //有虚函数,因此是多态基类
public:
virtual ~Base() {}
};
class Derived : public Base {
};
int main() {
Base b;
Derived d;
Derived *pd;
pd = reinterpret_cast<Derived *> ( &b);
if (pd == NULL)
//此处pd不会为NULL。reinterpret_cast不检查安全性,总是进行转换
cout << "unsafe reinterpret_cast" << endl; //不会执行
pd = dynamic_cast<Derived *> ( &b);
if (pd == NULL)
//结果会是NULL,因为 &b不是指向派生类对象,此转换不安全
cout << "unsafe dynamic_cast1" << endl; //会执行
pd = dynamic_cast<Derived *> ( &d); //安全的转换
if (pd == NULL) //此处pd 不会为NULL
cout << "unsafe dynamic_cast2" << endl; //不会执行
return 0;
}
unsafe dynamic_cast1
Derived & r = dynamic_cast
那该如何判断该转换是否安全呢?
答案:不安全则抛出异常
try块中定义的局部对象,发生异常时会析构!
int main(){
double m ,n;
cin >> m >> n;
try {
cout << "before dividing." << endl;
if( n == 0)
throw -1; //抛出int类型异常
else if( m == 0 )
throw -1.0; //抛出double型异常
else
cout << m / n << endl;
cout << "after dividing." << endl;
}
catch (double d){
cout << "catch(double) " << d << endl;
}
catch(int e) {
cout << "catch(int) " << e << endl;
}
cout << "finished" << endl;
return 0;
}
如果一个函数在执行的过程中,抛出的异常在本函数内就被catch块捕获并处理了,那么该异常就不会抛给这个函数的调用者(也称“上一层的函数”);如果异常在本函数中没被处理,就会被抛给上一层的函数。
class CException {
public :
string msg;
CException(string s) : msg(s) {}
};
double Devide(double x, double y) {
if (y == 0)
throw CException("devided by zero");
cout << "in Devide" << endl;
return x / y;
}
int CountTax(int salary) {
try {
if (salary < 0)
throw -1;
cout << "counting tax" << endl;
}
catch (int) {
cout << "salary < 0" << endl;
}
cout << "tax counted" << endl;
return salary * 0.15;
}
int main() {
double f = 1.2;
try {
CountTax(-1);
f = Devide(3, 0);
cout << "end of try block" << endl;
}
catch (CException e) {
cout << e.msg << endl;
}
cout << "f=" << f << endl;
cout << "finished" << endl;
return 0;
}
C++标准库中有一些类代表异常,这些类都是从exception类派生而来
在用new运算符进行动态内存分配时,如果没有足够的内存,则会引发此异常。
using namespace std;
int main() {
try {
char *p = new char[0x7fffffffffff];
//无法分配这么多空间,会抛出异常
}
catch (bad_alloc &e) {
cerr << e.what() << endl;
}
return 0;
}
用vector或string的at成员函数根据下标访问元素时,如果下标越界,就会抛出此异常。
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v(10);
try {
v.at(100) = 100; //抛出out_of_range异常
}
catch (out_of_range &e) {
cerr << e.what() << endl;
}
string s = "hello";
try {
char c = s.at(100); //抛出out_of_range异常
}
catch (out_of_range &e) {
cerr << e.what() << endl;
}
return 0;
}
C++运算符typeid是单目运算符,可以在程序运行过程中获取一个表达式的值的类型。typeid运算的返回值是一个type_info类的对象,里面包含了类型的信息。
typeid和type_info用法示例:
using namespace std;
struct Base {
}; //非多态基类
struct Derived : Base {
};
struct Poly_Base {
virtual void Func() {}
}; //多态基类
struct Poly_Derived : Poly_Base {
};
int main() {
//基本类型
long i;
int *p = NULL;
cout << "1) int is: " << typeid(int).name() << endl;
//输出 1) int is: int
cout << "2) i is: " << typeid(i).name() << endl;
//输出 2) i is: long
cout << "3) p is: " << typeid(p).name() << endl;
//输出 3) p is: int *
cout << "4) *p is: " << typeid(*p).name() << endl;
//输出 4) *p is: int
//非多态类型
Derived derived;
Base *pbase = &derived;
cout << "5) derived is: " << typeid(derived).name() << endl;
//输出 5) derived is: struct Derived
cout << "6) *pbase is: " << typeid(*pbase).name() << endl;
//输出 6) *pbase is: struct Base
cout << "7) " << (typeid(derived) == typeid(*pbase)) << endl;
//输出 7) 0
//多态类型
Poly_Derived polyderived;
Poly_Base *ppolybase = &polyderived;
cout << "8) polyderived is: " << typeid(polyderived).name() << endl;
//输出 8) polyderived is: struct Poly_Derived
cout << "9) *ppolybase is: " << typeid(*ppolybase).name() << endl;
//输出 9) *ppolybase is: struct Poly_Derived
cout << "10) " << (typeid(polyderived) != typeid(*ppolybase)) << endl;
//输出 10) 0
}