C++ language Learn:
https://www.programiz.com/cpp-programming/variables-literals
Keywords of C++ alignas(c++11) //声明结构体或类的对齐数
alignof(c++11) //查看结构体或类的对齐数
and //等价于 &&
and_eq //等价于 &&=
asm //汇编语句
auto //自动类型
bitand //等价于 &
bitor //等价于 |
bool //bool类型
break //跳出当前循环,或switch
case //结合switch使用
catch //捕获异常
char //1字节变量
short //2字节变量
signed //声明为有符号类型
unsigned //声明为无符号类型
char16_t(c++11) //常使用于Unicode字符
char32_t(c++11) //常使用于Unicode字符
int //默认4字节
long //不比int类型小的类型
class //类,或者声明模板类型
compl //等价于 ~
concept(概念Ts) //专家级别使用
const //声明常变量
constexpr(c++11) //用作函数时,是在编译是进行函数调用的,类似与宏
const_cast //常变量强制转化为其他变量类型
continue //结合循环来使用
decltype(c++11) //与auto差不多,可以用于某个不确定多个参数类型的模板函数
default //结合switch来使用
delete //释放new出来的东西
new //开辟内存
do //配合 while构成循环
explicit //不能隐式构造
export //专家级别使用...
extern //改变某个变量的作用域,常用在不同文件中使用同一个变量
float //4字节的浮点类型
double //8字节的浮点类型
for //for循环
goto //跳转
if //判断
friend //给类中的一些函数使用,可以访问类中的私有成员变量
inline //内联声明, 编译器对该函数进行优化,类中函数和模板函数默认代这个参数
mutable //在lambda表达式中使用表示为传递进来的变量可以被赋值
namespace //声明命名空间
noexcept(c++11) //声明为不抛出异常,利于编译器的优化
not //等价与 !
not_eq //等价于 !=
nullptr(c++11) //c++11以后声明空指针类型,主要解决模板函数中的参数问题
operator //操作运算重载
or //等价与 |
or_eq //等价于 |=
private //声明成员为私有的
public //声明成员为公共的
protected //声明成员为保护的
register //声明在寄存器里的变量
reinterpret_cast //常用在 一个类型的指针转化为另一个类型的指针
requires(概念TS) //一个概念,目前还没有编译器实现
return //函数的返回
static //声明变量为静态的
sizeof //获取某个变量的大小
static_assert(c++11) //静态断言, 常用
static_cast //静态转化
struct //结构体类型
switch //switch分支判断结构
template //声明模板
this //this指针, 常用在class和struct
thread_local(c++11) //结合线程来使用
throw //抛出异常
true //bool类型的真
false //bool类型的假
try //异常尝试
typedef //改变变量名称
typeid //获取类型的id号
typename //声明模板类型
union //联合体
using //可以替换typedef的功能
virtual //虚函数
void //空类型
volatile //直接声明为定死的常量
wchar_t //表示宽字符的
while //循环
xor //异或 ^
xor_eq // ^=
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 #include <iostream> #include <typeinfo> #include <cassert> #include <map> using namespace std;struct alignas (8 ) S {};struct alignas (1 ) U {S s; }; struct Foo { int i; float f; char c; };struct Empty {};struct alignas (64 ) Empty64 {};struct alignas (1 ) Double { double d; };struct Obj {char a; int b;};void alignInfo () { cout << "Alignment of" << endl <<"_char : " << alignof (char ) << endl <<"_pointer : " << alignof (int *) << endl <<"_class Foo : " << alignof (Foo) << endl; }void showAnd () { int a = 3 ; int b = 4 ; if (a == 3 && b == 4 ) { cout << "&& a = 3, b = 4" ; } if (a == 3 and b == 4 ) { cout << "and a = 3, b = 4" ; } }void testAnd_eq () { bool a = false ; bool b = true ; b = b and_eq a; cout << b << endl; bool c = true ; c and_eq a; cout << "c: " << c << endl; }void testNot () { bool a = true ; bool b = not (a); cout << b; }void testNot_eq () { bool a = true ; a not_eq (a) ; cout << a; }void testOr () { int a = 3 ; cout << a or 2 ; }void testOr_eq () { int a = 3 ; a or_eq 4 ; cout << a; }void showAsm () { asm ( "movq $60, %rax\n\t" "movq $2, %rdi\n\t" "syscall" ); }int get_fun (int x) { return x + 1 ; }double add (double a, double b) { return a + b; }void showAuto () { auto a = 1 + 2 ; cout << "type of a: " << typeid (a).name () << endl; auto b = add (1 , 1.2 ); cout << "type of b: " << typeid (b).name () << endl; auto c = {1 , 2 }; cout << "type of c: " << typeid (c).name () << endl; auto my_lambda = [](int x) { return x + 3 ; }; cout << "type of my_lambda: " << typeid (my_lambda).name () << endl; auto my_fun = get_fun; cout << "my_fun: " << my_fun (3 ) << endl; cout << "type of my_fun: " << typeid (my_fun).name () << endl; }void showBitAndOr () { auto a = 3l ; auto b = 4 ; auto c = a bitand b; auto d = a bitor b; cout << "c: " << c << "d: " << d; }void testBool () { bool a = true ; bool b = false ; *(reinterpret_cast <char *>(&a)) = -1 ; cout << a << " " << b << endl; if (a == true ) { cout << "i'm true" ; }else if (a == false ){ cout << "i'm false" ; }else { cout << "What?" ; } }void testBreak () { int a = 10 ; for (;;) { for (;;) { ++a; if (a > 1000 ) break ; } if (a > 100000000 ) break ; } }void testCompl () { int a = -3 ; int b = compl (a); cout << b; }int fact (int n) { return n < 1 ? 1 : (n * fact (n - 1 )); }constexpr int factorial (int n) { return n < 1 ? 1 : (n * factorial (n - 1 )); }template <int N>struct NN { void print () { cout << N << endl;} };void testConstExpr () { auto a = fact (4 ); auto b = factorial (4 ); cout << "a: " << a << " b: " << b << endl; char group[factorial (5 )]; NN<factorial (8 )> nn; nn.print (); }void testConst_cast () { const int i = 3 ; int *p = const_cast <int *>(&i); *p = 5 ; cout << p << endl << &i << endl; cout << i << " " << *p << endl; }struct A {A (int n) : x (n) {} double x;};void testDecltype () { const A* a = new A (0 ); auto aa = a->x; decltype (a->x) y; decltype ((a->x)) z = y; y = 3 ; cout << y << endl << z; }template <typename T, typename U>auto add (T a, U b) -> decltype (a + b) { return a + b; }struct Base { virtual ~Base () {} };struct Drive : Base { virtual void name () {} };void testDynamic_cast () { Base *b1 = new Base; if (Drive *d = dynamic_cast <Drive *>(b1)) { std::cout << "downcast from b1 to d successful" << std::endl; d->name (); } Base *b2 = new Drive; if (Drive *d = dynamic_cast <Drive *>(b2)) { std::cout << "downcast from b2 to d successful" << std::endl; d->name (); } }enum Color { red, green, blue };void testOldEnum () { Color r = red; switch (r) { case red: std::cout << "red" << std::endl; break ; case green: std::cout << "green" << std::endl; break ; case blue: std::cout << "blue" << std::endl; break ; default : std::cout << "what ?" << std::endl; } }enum class NewColor {red, green, blue = green + 12 };enum class MyColor : short {black}; enum class IsGood {Yes, No};enum class IsOk {Yes, No};void enumBoolTest (IsGood isGood, IsOk isOk) { }void testNewEnum () { NewColor r = NewColor::blue; switch (r) { case NewColor::blue: { cout << "new blue" << endl; } break ; case NewColor::red: { cout << "new red" << endl; } break ; case NewColor::green: { cout << "new green" << endl; } break ; default : cout << "new what?" << endl; } int i = static_cast <int >(blue) + static_cast <int >(NewColor::blue); cout << "blud + NewColor::blue = " << i << endl; enumBoolTest (IsGood::Yes, IsOk::No); }struct AA { AA (int ) {} AA (int , int ) {} operator int () const { return 0 ; } };struct BB { explicit BB (int ) {} BB (int , int ) {} explicit operator int () const { return 0 ; } };void testExplicit () { AA a1 = 1 ; AA a2 = {3 , 5 }; BB b2 = {3 , 5 }; int i = a1; int na2 = static_cast <int >(a1); int nb2 = static_cast <int >(b2); AA a4 = (AA)3 ; BB b3 = (BB)4 ; }class MyClass {};class Friend { private : int data; friend std::ostream &operator << (std::ostream &out, const Friend &o); template <typename T> friend class MyCla ; template <typename T> friend void f (T) {} public : Friend (int x) : data (x) {} operator int () const { return this ->data; } }; std::ostream &operator << (std::ostream &out, const Friend &f) { return out << f.data; }class Friend2 : public Friend { };void testFriend () { Friend a = 44 ; cout << a; }void testGoto () { auto i = 0 ; NO: if (i < 5 ) { cout << i; i ++; goto NO; } }inline int plus (int a, int b) { return a + b; }class Inline { public : void Member () const { std::cout << "hello\n" ; } int vlaue () const { return this ->m_value; } private : int m_value; };namespace XGroup { class A_ { int value; }; }namespace YGroup { class A_ { int value; }; class B_ { int value; }; }void testNmaespace () { XGroup::A_ a; YGroup::A_ b; }void testNamespace2 () { using namespace XGroup; A_ a; using namespace YGroup; B_ b; }void testNamespace3 () { namespace CGroup = XGroup; CGroup::A_ a; using YGroup::B_; B_ b; }namespace { std::string astring ("long" ) ; }void testNamespace4 () { cout << astring; }void noexCept () noexcept { std::cout << "hello" << std::endl; }void noexCept2 () noexcept (false ) { std::cout << "hello" << std::endl; }void nullPointer (int *a) { }template <typename T, typename U>void func (T t, U u) { t (u); }void testNullPointer () { nullPointer (0 ); nullPointer (NULL ); nullPointer (nullptr ); func (nullPointer, nullptr ); func (nullPointer, (int *)0 ); func (nullPointer, (int *)NULL ); }struct Operator { public : Operator (int x) : data (x) { } int operator << (Operator const & o) const { return data + o.data; } int operator & () const { return data; } private : int data; };void testOperator () { Operator a = 10 ; Operator b = 5 ; Operator c = a << b; cout << &c << endl; }struct AClass { ~AClass () { delete m_value;} AClass (const AClass& rhs) : m_value (new int (*(rhs.m_value))) {} AClass& operator = (const AClass& rhs) { *m_value = *(rhs.m_value); return *this ; } private : int *m_value; };void testReinterpret_cast () { int a = 1 ; auto p = reinterpret_cast <char *>(&a); if (p[0 ] = 1 ) { std::cout << "the system is little endian\n" ; }else { std::cout << "the system is big endian\n" ; } }struct SizeofEmpty {};struct SizeofBase { int a;};struct SizeofDerived : Base{ int b;};struct SizeofBit {unsigned bit : 1 ;};void testSizeof () { SizeofEmpty e; SizeofDerived d; SizeofBase b; SizeofBit bit; cout << "sizeof empty: " << sizeof e << endl; cout << "sizeof derived: " << sizeof d << endl; cout << "sizeof base: " << sizeof (b) << endl; cout << "sizeof bit: " << sizeof (SizeofBit) << endl; }static int globalA = 0 ;void printInfo () { static int localStatic = 0 ; ++ localStatic; cout << "globalA: " << globalA << " " << "localStatic: " << localStatic << endl; }struct Static { static int s; };int Static::s = 10 ;struct HeHe {};struct Static2 { static int a[]; static HeHe foo; static Static2 ss; };int Static2::a[10 ]; HeHe Static2::foo; Static2 Static2::ss;void testStaticAssert () { static_assert (sizeof (int ) == 4 , "only work for int of 32bit" ); static_assert (sizeof (long ) == sizeof (long long ), "only work for int of 32bit" ); int a = 5 ; int b = 5 ; assert (a != b && "error" ); }template <typename T>void static_assertFun () { static_assert (alignof (T) ==4 , "only for alignof 4" ); }typedef unsigned long ulong;class Comp { typedef std::map<int , ulong> Group; Group a; void aa () { Group::iterator iter = a.find (10 ); } };using newGroup = std::map<int , ulong>;int main (void ) { testStaticAssert (); return 0 ; }
Class C++析构函数中抛出异常问题 注意: 不要在析构函数中抛出异常
析构函数调用规则
先调用成员析构
再调用派生类析构
问题代码 分析代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <iostream> class A { public : A () {} ~A () { std::cout << "A析构了.." << std::endl; } };class B : public A{ public : B () {} ~B () { std::cout << "B析构了.. " << std::endl; throw std::string ("B error" ); } private : std::string m_value; };void testClass_1 () { B *b = new B; delete b; }class EvilB : public B { public : ~EvilB () noexcept (false ) { throw std::string ("error" ); } };void testEvilB () { try { EvilB *b = new EvilB (); delete b; } catch (std::string e) { std::cout << "catch your evil: " << e << std::endl; } }int main (void ) { testEvilB (); return 0 ; }
正确做法 建议: 在类的构造函数中抛出异常
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #include <iostream> #include <fstream> #include <vector> #include <cassert> class A { public : A () {} };class B : public A { public : B () {} ~B () { } private : std::string m_value; };class GoodB : public B { public : GoodB () : m_v (new char (10000000 )) {} GoodB (const char * f) : m_file (f, std::ios_base::in) { if (!m_file.is_open ()) throw std::string ("Couldn't open file..\n" ); std::string line; while (std::getline (m_file, line)) { m_info.push_back (line); } } void doIt ( GoodB const &b) { if (b.isOpen ()) { } } ~GoodB () { assert ((!isOpen ()) && "open file: " ); } private : char *m_v; std::fstream m_file; std::vector<std::string> m_info; bool isOpen () const { return !m_info.empty (); } };void test () { int i = 0 ; for (;;) { try { ++i; if (i % 10000 == 0 ) std::cout << "count i: " << i << std::endl; GoodB b; } catch (...) { return ; } } }void test2 (char *filename) { try { GoodB b (filename) ; GoodB d (filename) ; b.doIt (b); } catch (std::string msg) { std::cout << msg; } }int main (int argc, char ** argv) { if (argc <= 1 ) return 1 ; test2 (argv[1 ]); std::cout << "exit!!!\n" ; return 0 ; }
管理内存的几种方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <iostream> #include <memory> static void versionOne () ;static void versionTwo () ;using namespace std;int main (void ) { versionOne (); versionTwo (); versionThree (); return EXIT_SUCCESS; }void versionOne () { int *ageC = (int *) malloc (sizeof (int )); if (argC) { free (ageC); } char *c = (char *) malloc (100 ); free (c); int *age = new int (25 ); int *height = new int (160 ); }void versionTow () { std::shared_ptr<int > age (new int (28 )) ; std::shared_ptr<int > height (new int (160 )) ; std::cout << "VersionTwo: you age is " << *age << ", and your height is " << *height << std::endl; }
逐渐退化的虚函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <map> #include <iostream> class Event ; class Event {};class Base { public : virtual ~Base () {} Base (int _id) : m_id (_id) {} virtual void act (Event const &) = 0 ; virtual void print () const = 0 ; int id () const { return m_id; } private : int m_id; };class Drived : public Base { public : void act (Event const &) ; void print () const ; Drived (int id); ~Drived (); private : };class Grouped : public Base { public : void act (Event const &) ; void print () const ; void addBase (Base* b) ; void removeBase (int id) ; Grouped (int id); ~Grouped (); private : std::map<int , Base *> m_info; };void test () { }int main (void ) { test (); return 0 ; }
虚函数几种实现方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <fstream> #include <iostream> #include <string> #include <vector> struct Base { virtual void f () { std::cout << "base" << std::endl; } virtual void init () {} Base () { init (); } };struct Derived : Base { void f () override { std::cout << "derived overide" << std::endl; } void init () override { std::cout << "virtual init" << std::endl; } } ;struct Derived2 : Derived { public : void f () {} void init () {} };Base* factoryBase (int type) { Base* ret = nullptr ; if (type == 0 ) { ret = new Base (); }else if (type == 1 ) { ret = new Derived (); }else if (type == 2 ) { ret = new Derived2 (); } if (ret) ret->init (); return ret; }void testVirtual () { Derived d; }int main (void ) { testVirtual (); return 0 ; }
对象内存布局 普通对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> class A {public : A () { std::cout << "A\n" ; } ~A () { std::cout << "~A\n" ; }private : int a = 1 ; int b = 2 ; };int main () { A a; return 0 ; }
生成可执行文件ida反编译如下:
main
1 2 3 4 5 6 7 8 9 10 int __cdecl main (int argc, const char **argv, const char **envp) { char v4[8 ]; unsigned __int64 v5; v5 = __readfsqword(0x28 u); A::A ((A *)v4); A::~A ((A *)v4); return 0 ; }
A::A()
1 2 3 4 5 6 void __fastcall A::A (A *this ) { *(_DWORD *)this = 1 ; *((_DWORD *)this + 1 ) = 2 ; std::operator <<<std::char_traits<char >>(&std::cout, &unk_2005); }
A::~A()
1 2 3 4 void __fastcall A::~A (A *this ) { std::operator <<<std::char_traits<char >>(&std::cout, &unk_2008); }
this指针即是堆栈上数据v4的地址。
在堆区上的普通对象 source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> class A {public : A () { std::cout << "A\n" ;} ~A () { std::cout << "~A\n" ;} void test () { std::cout << "test\n" ;}private : int a = 1 ; int b = 2 ; };int main () { A *a = new A (); a->test (); return 0 ; }
生成可执行文件ida反编译如下:
1 2 3 4 5 6 7 8 9 int __cdecl main (int argc, const char **argv, const char **envp) { A *v3; v3 = (A *)operator new (8uLL ); A::A (v3); A::test (v3); return 0 ; }
A::A()
1 2 3 4 5 6 void __fastcall A::A (A *this ) { *(_DWORD *)this = 1 ; *((_DWORD *)this + 1 ) = 2 ; std::operator <<<std::char_traits<char >>(&std::cout, &unk_2005); }
与堆栈上的差不多, 堆栈上的对象不用管内存泄漏问题,编译器调用析构函数,开辟在堆区的对象由于没有delete a,所有没有析构函数调用和内存的释放,出现内存泄漏。
拥有vital function 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> class A {public : A () { std::cout << "A\n" ; } ~A () { std::cout << "~A\n" ; } virtual void vir_1 () { std::cout << "vir_1 A\n" ; } virtual void vir_2 () = 0 ;private : int a; int b; };class B : public A{public : B () {std::cout << "B\n" ;} ~B () {std::cout << "~B\n" ;} virtual void vir_2 () { }private : int a = 4 ; };int main () { B a; return 0 ; }
生成可执行文件ida反编译如下:
main
1 2 3 4 5 6 7 8 9 10 int __cdecl main (int argc, const char **argv, const char **envp) { char v4[24 ]; unsigned __int64 v5; v5 = __readfsqword(0x28 u); B::B ((B *)v4); B::~B ((B *)v4); return 0 ; }
B::B()
1 2 3 4 5 6 7 8 9 10 11 12 13 void __fastcall B::B (B *this ) { A::A (this ); *(_QWORD *)this = off_3D68; *((_DWORD *)this + 4 ) = 4 ; std::operator <<<std::char_traits<char >>(&std::cout, "B\n" ); }
A::A()
1 2 3 4 5 6 7 8 9 10 void __fastcall A::A (A *this ) { *(_QWORD *)this = &off_3D88; std::operator <<<std::char_traits<char >>(&std::cout, &unk_2005); }
B::~B()
1 2 3 4 5 6 void __fastcall B::~B (B *this ) { *(_QWORD *)this = off_3D68; std::operator <<<std::char_traits<char >>(&std::cout, "~B\n" ); A::~A (this ); }
A::~A()
1 2 3 4 5 void __fastcall A::~A (A *this ) { *(_QWORD *)this = &off_3D88; std::operator <<<std::char_traits<char >>(&std::cout, &unk_2008); }
由以上看类中的内容是储存在ptr + 1之后的,第一个用于储存虚函数表的地址。
ref: https://www.cnblogs.com/qg-whz/p/4909359.html
基本原则 C++98 类的基本三大原则
类的构造
类的析构
类的复制
若c++98中,不想复制的话,把构造函数设为私有变量, 并不实现构造函数 不然编译器会自动生成一个对应的构造函数
C++11 类的基本五大原则 前面三点基于c++98,增加了两个原则
5 可以对拷贝构造函数和operator=进行右值引用进行重载
也就是采用左值或者右值进行构造,编译器会对不同的构造函数进行构造.
代码例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 #include <iostream> #include <string> #include <vector> #include <cstring> #include <cassert> class RuleOfFive ; class Parent ;class Child { public : explicit Child (Parent *p) : m_parent(p) { } private : Parent *m_parent; };class Parent { public : bool addChild (Child* child) {m_children.emplace_back (child); } private : std::vector<Child*> m_children; };class RuleOfThree { public : RuleOfThree (const char * arg) : cstring (new char [std::strlen (arg) + 1 ]){ std::strcpy (cstring, arg); } ~RuleOfThree () { delete [] cstring; } RuleOfThree (const RuleOfThree& other) = delete ; RuleOfThree& operator = (const RuleOfThree& other) { char *tmp_cstring = new char [std::strlen (other.cstring) + 1 ]; std::strcpy (tmp_cstring, other.cstring); delete [] cstring; } private : char * cstring; };class RuleOfFive { public : RuleOfFive (RuleOfFive&& rhs) { std::cout << "右值构造.." << std::endl; std::cout << rhs.m_value; m_value = rhs.m_value; rhs.m_value = nullptr ; }; RuleOfFive () : m_value (new int (10 ) ) {} RuleOfFive (const RuleOfFive &rhs) : m_value (new int (* (rhs.m_value))) { std::cout << "左值或者右值构造.." << std::endl; } RuleOfFive& operator = (const RuleOfFive &rhs) { delete m_value; *m_value = *(rhs.m_value); return *this ; } RuleOfFive& operator =(RuleOfFive&& rhs) { m_value = rhs.m_value; rhs.m_value = nullptr ; return *this ; } void print () const { assert (m_value && "class print: " ); std::cout << "value: " << *m_value << std::endl; } ~RuleOfFive () { delete m_value; } private : int *m_value; };void leftOrRight () { int a = 0 ; int b; int c = 2 + 3 ; int d = a + c; auto address = &a; int & e = a; int && e3 = 3 ; }void leftAndRight () { std::vector<int > a; for (int i = 0 ; i < 10 ; ++i) a.push_back (i); auto b = a; auto &c = b; auto d = std::move (b); RuleOfFive f; RuleOfFive g (f) ; RuleOfFive h (std::move(f)) ; }int main (void ) { leftAndRight (); return 0 ; }
STL STL 是一个框架, 将数据结构和算法进一步的抽象, 包含了容器, 迭代器, 算法 容器: 储存数据的
迭代器: 容器之间统一的一个查询元素接口,可以用来遍历容器的元素
算法: 查找, 排序, 修改…
类别 1 序列式容器 array / vector / deque/list / forward_list 一般实现方式: 数组 ,指针 链表 2 关联类有序容器 set / map / multiset / multimap 实现方式: 二叉树, 红黑树 3 关联类无序容器 unordered_map / unordered_set / unordered_multimap / unordered_multiset 实现方式: hash table, 哈希表 4 其他容器: stack / queue / priority_queue / string / bitset (存储对或错)
新型: regex (正则表达式), 增强了 rand算法, thread(线程), async, furture, time
容器内元素的条件
必须可以复制(copy) 或则搬移(move) (隐含的条件是在拷贝和搬移的过程中应该没有副作用)
c++ 的基本类型满足以上要求: bool char int int* char*, reference
元素必须可以被赋值操作,来作为复制或者搬移, (因为容器和算法对复写有要求)
元素可以被销毁
针对于不同的容器还有特殊的要求
对于序列式容器, 元素必须有默认的构造函数
对于某些操作,元素需要定义 ==
对于关联式容器, 排序默认准则的是 <
无顺序容器,必须要提供一个hash函数
stl容器里面存的是元素的值而不是引用,到底我们的容器里面应该存的东西是什么呢?
STL对于错误怎么处理 我们要记住的是STL的设计原则是: 效率优先, 安全为次 异常? STL自己却不怎么用
实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include <iostream> #include <chrono> #include <algorithm> #include <list> #include <map> #include <random> #include <set> #include <string> #include <unordered_map> #include <unordered_set> #include <vector> #include <deque> template <typename T>void containerAllInterface (T &a, T &b) { T c; T d (a) ; T e = a; T ee {a}; T eee = {a}; T f (std::move(a)) ; auto iterB = b.begin (); auto iterE = b.end (); typename T::iterator iterF = b.begin (); T g (b.begin(), b.end()) ; T g2 (iterB, iterE) ; b.size (); b.empty (); b.max_size (); if (b == c) {} if (b != d) {} if (b < e) {} e = b; e = std::move (b); e.swap (g); std::swap (e, g); e.cbegin (); auto ea = e.cbegin (); auto eea = e.cbegin (); *eea; *ea; e.cend (); e.clear (); }void test_container () { std::vector<int > a; std::vector<int > b; containerAllInterface<std::vector<int >>(a, b); std::list<int > e; std::list<int > f; containerAllInterface<std::list<int >>(e, f); std::deque<int > g; std::deque<int > h; containerAllInterface<std::deque<int >>(g, h); }int main (int , char **) { return 0 ; }
vector vector 是c++98中引入的动态数组(dynamic array)
1 2 3 4 namespace std {template <typename T, typename Allocator = allocator<T>> class vector; }
特点
随机访问元素, 末端添加删除元素效率最高, 前端和中间删除和添加元素效率最低,存在当前容器大小和容量的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 #include <vector> #include <iostream> #include <cstring> static void vectorPart () {using Group = std::vector<float >; Group a; Group b = a; Group c (a) ; Group d (10 ) ; Group e (10 , 1.0f ) ; Group f (e.begin(), e.end()) ; Group g ({1.0f , 2.0f , 3.0f }) ; Group h = {1.1f , 2.1f , 3.1f }; Group i {1.2f , 2.2f , 3.2f , 4.2f }; d.empty (); d.size (); d.max_size (); d.capacity (); d.reserve (100 ); d.shrink_to_fit (); b = g; b.assign (3 , 1.0f ); b.assign (g.begin (), g.end ()); b.assign ({1.0f , 2.0f , 3.0f }); b.swap (a); std::swap (a, b); b[0 ]; b.at (0 ); if (b.empty ()) { b.front (); b.back (); } b.front (); b.back (); a.begin (); a.end (); a.cbegin (); a.cend (); a.rbegin (); a.rend (); a.crbegin (); a.crend (); a.pop_back (); b.erase (b.begin ()); b.erase (b.begin (), b.end ()); b.push_back (10.0f ); b.pop_back (); auto iter = b.insert (b.end (), 100.0f ); iter = b.insert (b.end (), 10 , -10.0f ); b.insert (b.end (), h.begin (), h.end ()); b.emplace (b.end (), 10.0f ); b.emplace_back (10.0f ); b.resize (10 ); b.resize (100 , 1.0f ); b.clear (); b.shrink_to_fit (); std::vector<char > carr (100 , 0 ) ;strcpy (&carr[0 ], "hello World\n" ); printf ("%s" , carr.data ());printf ("%s" , carr.begin ()); }int main (int , char **) { return 0 ; }
deque deque是c++98中引入的动态数组(dynamic array)
1 2 3 4 namespace std {template <typename T, typename Allocator = allocator<T>>class deque; }
特点
随机访问元素, 末端和头部添加删除元素效率高,中间删除和添加元素效率低,而vector仅仅操作尾部效率高,元素的访问和迭代比vector要慢,迭代器不能是普通的指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 #include <deque> #include <vector> using Group = std::deque<float >;static void dequePart () { Group a; Group b = a;Group c (a) ;Group d (10 ) ;Group e (10 , 1.0f ) ;Group f (e.begin(), e.end()) ;Group g ({1.0f , 2.0f , 3.0f }) ; Group h = {1.0f , 2.0f , 3.0f }; Group i {1.0f , 2.0f , 3.0f };if (!a.empty ()) a.pop_back (); d.empty (); d.size (); d.max_size (); d.shrink_to_fit (); b.swap (a); std::swap (a, b); b[0 ]; b.at (0 ); b.front (); b.back (); a.begin (); b.end (); a.cbegin (); a.cend (); a.rbegin (); a.rend (); a.crbegin (); a.crend (); a.pop_back (); a.push_back (1.0f ); a.push_front (1.2f ); b.emplace_front (1.0f );auto iter = b.insert (b.end (), 100.0f ); b.insert (b.end (), 10 , -10.0f ); b.insert (b.end (), h.begin (), h.end ()); b.emplace (b.end (), 10.0f ); b.emplace_back (10.0f ); b.resize (10 ); b.resize (100 , 10.0f ); b.clear (); b.shrink_to_fit (); }int main (void ) { return 0 ; }
list list 是c++98中引入的双向串列(double linked list)
1 2 3 4 namespace std { template<typename T, typename Allocator = allocator<T>> class list; }
特点
不支持随机访问元素,访问头部和尾部元素快 任何位置插入删除元素都很快,常亮时间内完成 插入和删除不会造成迭代器的失效 对于异常支持好, 出现异常对于list而言, 要么不成功, 要么没有影响
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 #include <list> #include <cassert> #include <iostream> static void listPart () {using Group = std::list<float >; Group a; Group b = a;Group c (a) ;Group d (10 ) ;Group e (10 , 1.0f ) ;Group f (e.begin(), e.end()) ;Group g ({1.0f , 2.0f , 3.0f }) ; Group h = {1.0f , 2.0f , 3.0f }; Group i {1.0f , 2.0f , 3.0f }; d.empty (); d.size (); d.max_size (); b = g; b.assign (3 , 1.0f ); b.assign (g.begin (), g.end ()); b.assign ({1.0f , 2.0f , 3.0f }); b.swap (a); std::swap (a, b); b.front (); b.back (); a.begin (); a.end (); a.cbegin (); a.cend (); a.rbegin (); a.rend (); a.crbegin (); a.crend (); a.resize (10 );auto iterBegin = a.begin ();assert (a.size () >= 10 ); std::advance (iterBegin, 0 ); for (; iterBegin != a.end (); ++iterBegin) std::cout << *iterBegin << " " ; a.pop_back (); if (!a.empty ()) a.pop_back (); b.erase (b.begin ()); b.erase (b.begin (), b.end ()); b.push_back (10.0f ); b.pop_back (); b.push_front (1.2f ); b.emplace_front (1.3f );auto iter = b.insert (b.end (), 100.0f ); iter = b.insert (b.end (), 10 , -10.0f ); b.resize (5 ); b.resize (10 , 1.2f ); b.remove (1.0f ); b.remove_if ([](auto v) { return v > 100.0f ; }); b.reverse (); b.sort (); b.merge (g); c.unique (); c.splice (c.begin (), b); }int main (void ) { listPart (); return 0 ; }
forward_list //forward_list 是c++11中引入的单项串列(singal linked list)
1 2 3 4 namespace std {template <typename T, typename Allocator = allocator<T>>class forward_list; }
特点
不支持随机元素访问, 访问头部元素速度快,”forward_list” 和自己手写的c-style signal linked list相比没有任何时间和空间上的额外开销, 任何性质如果和这个目标抵触,我们就放弃该特征.任何位置插入和删除元素都很快, 常亮时间完成。插入和删除不会造成迭代器失效,对于异常支持好, 出现异常对于forward_lit而言, 要么不成功, 要么没什么影响。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 #include <forward_list> #include <iostream> static void forwardListPart () {using Group = std::forward_list<float >; Group a; Group b = a;Group c (a) ;Group d (10 ) ;Group e (10 , 1.0f ) ;Group f (e.begin(), e.end()) ;Group g ({1.0f , 2.0f , 3.0f }) ; Group h = {1.0f , 2.0f , 3.0f }; Group i {1.0f , 2.0f , 3.0f }; d.empty (); d.max_size (); b = g; b.assign (3 , 1.0f ); b.assign (g.begin (), g.end ()); b.assign ({1.0f , 2.0f , 3.0f }); b.swap (a); std::swap (a, b); b.front (); a.begin (); a.end (); a.cbegin (); a.cend (); a.before_begin (); a.cbefore_begin (); auto iterBegin = a.begin (); a.empty (); b.erase_after (b.begin ()); b.erase_after (b.before_begin ()); b.erase_after (b.begin (), b.end ()); b.push_front (1.2f ); b.emplace_front (1.3f );auto iter = b.insert_after (b.before_begin (), 100.0f ); iter = b.insert_after (b.before_begin (), 10 , -10.0f ); b.insert_after (b.before_begin (), h.begin (), h.end ()); b.resize (10 ); b.resize (100 , 1.0f ); b.remove (1.0f ); b.remove_if ([](auto v) { return v > 100.0f ; }); b.sort (); g.sort (); b.merge (g); c.unique (); c.splice_after (c.before_begin (), b); }int main (void ) { std::forward_list<int > forlist = {1 , 2 , 3 , 4 , 5 , 6 }; auto fiter = forlist.before_begin (); for (int i = 0 ; i < 2 ; ++i, ++fiter); forlist.insert_after (fiter, 10 ); for (fiter = forlist.begin (); fiter != forlist.end (); ++fiter) std::cout << *fiter << " " ; std::cout << std::endl; return 0 ; }
array array 实际上是对c/c++语言中的原生数组进行了封装
1 2 3 4 namespace std {template <typename T, size_t N> class array ; }
特点
内存分配在栈(stack), 绝不会重写分配.随机访问元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <iostream> #include <array> #include <cstring> template <typename C>void checkSize (C &c) { if (c.size () > 3 ) { c[3 ] = 10 ; } c.at (3 ) = 10 ; }void arrayPart () { std::array<int , 100> a; std::array<int , 100> b = {}; std::array<int , 5> obj = {1 , 2 , 3 , 4 , 5 }; std::array<int , 5> obj2 = {1 }; a.empty (); a.size (); a.max_size (); auto aa = a; aa.swap (a); a[1 ]; a.at (1 ); a.front (); a.back (); checkSize (a); a.begin (); a.end (); a.cbegin (); a.cend (); a.rbegin (); a.rend (); a.crbegin (); a.crend (); std::array<char , 100> carr; strcpy (&carr[0 ], "hello world\n" ); printf ("%s" , &carr[0 ]); printf ("%s" , carr.data ()); printf ("%s" , carr.begin ()); auto info = std::get <1 >(carr); printf ("%c\n" , info); carr.fill (0 ); }int main (void ) { arrayPart (); return 0 ; }
C++中的补码公式与位域 补码公式 -x = x+1 = ~(x-1) ~x = -x-1 -(x) = x+1 ~(-x) = x-1
x+y = x - y-1 = (x|y) + (x&y) x-y = x + ~y+1 = (x|y) - (x&y) x^y = (x|y) - (x&y) x|y = (x& ~y) + y x&y = (x|y) - ~x
x==y : (x-y|y-x) x!=y : x-y|y-x x<y : (x-y) ^ ((x^y) & ((x-y) ^x)) x<=y : (x|y) & ((x^y) | (y-x)) x<y : (x&y) | ((x|y) & (x-y)) //unsigned x<=y : (x|y) & ((x^y) | ~(y-x)) //unsigned
实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> using namespace std;void operator_1 (void ) ;void operator_2 (void ) ;void operator_3 (void ) ;int main (void ) { operator_1 (); operator_2 (); operator_3 (); return 0 ; }void operator_1 (void ) { int x = 1 ; cout << "-x = " << -x << " ~x+1 = " << ~x + 1 << endl; cout << "~x = " << ~x << " -x-1 = " << -x - 1 << endl; cout << "-(~x) = " << -(~x) << " x+1 = " << x + 1 << endl; cout << "-(~x) = " << -(~x) << " x-1 = " << -x -1 << endl; }void operator_2 (void ) { int x = 3 , y = 5 ; cout << endl; cout << "x: " << x << "y: " << y << endl; cout << "x+y=" << x+y << " x- ~y-1= " << x - ~y - 1 << " (x|y)+(x&y) = " << (x|y) + (x&y) << endl; cout << "x-y=" << x-y << " x+ ~y+1= " << x + ~y + 1 << " (x|~y) - (~x&y) = " << (x|~y) - (~x|y) << endl; cout << "x^y=" << (x^y) << " (x|y) - (x&y)" << (x|y) - (x&y) << endl; cout << "x|y=" << (x|y) << " (x& ~y) + y = " << (x& ~y) + y << endl; cout << "x&y=" << (x&y) << " (~x|y) - ~x = " << (~x|y) - ~x << endl; }void operator_3 (void ) { int x = -3 , y = -5 ; unsigned int x_t = -1 , y_t = -5 ; cout << "x: " << x << "y: " << y << endl; cout << "x==y =" << (x==y) << " ~(x-y|y-x) =" << ~(x-y|y-x) << endl; cout << "x!=y =" << (x!=y) << " x-y|y-x =" << (x-y|y-x) << endl; cout << "x<y =" << (x<y) << " (x-y) ^ ((x^y) & ((x-y)^x))=" << ((x-y) ^ ((x^y) & ((x-y)^x))) << endl; cout << "x<=y =" << (x<=y) << " (x|~y) & ((x^y) |~ (y-x))=" << ((x|~y) & ((x^y) |~ (y-x))) << endl; cout << "unsigned: x<y =" << (x_t <y_t ) << " (~x&y) | ((~x|y) & (x-y))" << ((~x_t &y_t ) | ((~x_t |y_t ) & (x_t -y_t ))) << endl; cout << "unsigned: x<=y =" << (x_t <=y_t ) << " (~x|y) & ((x^y) | ~(y-x) =" << ((~x_t |y_t ) & ((x_t ^y_t ) |~ (y_t -x_t ))) << endl; }
位域 在结构内声明位域的形式如下:
1 2 3 4 struct { type [member_name] : width ; };
下面是有关位域中变量元素的描述:
元素
描述
type
只能为 int(整型),unsigned int(无符号整型),signed int(有符号整型) 三种类型,决定了如何解释位域的值。
member_name
位域的名称。
width
位域中位的数量。宽度必须小于或等于指定类型的位宽度。
实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <stdio.h> typedef struct bs { int a:2 ; int b:1 ; int c:12 ; unsigned d:4 }bs;struct bit_2 { unsigned a:2 ; unsigned :2 ; unsigned :0 ; unsigned b:4 ; unsigned c:4 ; };int main (void ) { bs bit; printf ("sizeof(%d) \n" ,sizeof (struct bs)); bit.a = 4 ; bit.b = 1 ; bit.c = 34235 ; printf ("a: %d b: %d c: %d\n" , bit.a, bit.b, bit.c); return 0 ; }
lambda 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 #include <functional> #include <iostream> void printInfo (int a, int b, int c) { std::cout << " a " << a << " b " << b << " c " << c << std::endl; }struct Print { void operator () (int a, int b, int c) const { std::cout << " a " << a << " b " << b << " c " << c << std::endl; } };template <typename T1, typename T2, typename T3>void templatePrint (T1 a, T2 b, T3 c) { std::cout << " a " << a << " b " << b << " c " << c << std::endl; }struct TemplatePrint { template <typename T1, typename T2, typename T3> void operator () (T1 a, T2 b, T3 c) const { std::cout << " a " << a << " b " << b << " c " << c << std::endl; } };inline void print (int a, int b, int c) { std::cout << " a " << a << " b " << b << " c " << c << std::endl; }template <typename Fun>void printUseFun (Fun fun, int a, int b, int c) { fun (a, b, c); }void test_1 () { Print printUseClass; TemplatePrint printUseTempClass; printInfo (1 , 2 , 3 ); printUseClass (1 , 2 , 3 ); templatePrint (1 , 2 , 3 ); printUseTempClass (1 , 2 , 3 ); print (1 , 2 , 3 ); std::cout << "lamda: " << std::endl; auto local = [](int a, int b, int c) { std::cout << " a " << a << " b " << b << " c " << c << std::endl; }; printUseFun (local, 1 , 2 , 3 ); printUseFun ([](int a, int b, int c) { std::cout << "lamda2:" << std::endl; std::cout << " a = " << a << " b = " << b << " c = " << c << std::endl; }, 2 , 3 , 5 ); int a = 6 , b = 7 , c = 8 ; auto local2 = [a, b, c]() { std::cout << " a = " << a << " b = " << b << " c = " << c << std::endl; }; local2 (); auto local3 = [=]() { std::cout << "====" << std::endl; std::cout << " a = " << a << " b = " << b << " c = " << c << std::endl; }; local3 (); auto local4 = [=]() mutable { std::cout << "====" << std::endl; a = 4 , b = 4 , c = 4 ; std::cout << " a = " << a << " b = " << b << " c = " << c << std::endl; }; local4 (); }int main (void ) { test_1 (); return 0 ; }
C++11新型for循环,auto, 类成员的初始化及左右值引用 C++11中新型for循环,auto, 类成员的初始化及左右值引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 #include <typeinfo> #include <iostream> #include <string> #include <vector> #include <iterator> static void autoValue () ;static void autoPointer () ;static void newVersionFor () ;static void newVersionConstruct () ;static void defaultInitValue () ;static void leftRefAndRightRef () ;class MyVector { public : using GroupType = std::vector<int >; public : GroupType m_group; void push_back (int x) { m_group.push_back (x); } }; MyVector::GroupType::iterator begin (MyVector &v) { return v.m_group.begin (); } MyVector::GroupType::iterator end (MyVector &v) { return v.m_group.end (); }void testMyClass () { MyVector mv; mv.push_back (1 ); mv.push_back (2 ); mv.push_back (3 ); for (auto i : mv) { std::cout << i << " " ; } std::cout << std::endl; }int main (int , char ** ) { testMyClass (); leftRefAndRightRef (); return 0 ; }static void autoValue () { auto age = 10 ; auto name = std::string ("Yt" ); auto height = 160.0f ; auto wight = 72.0 ; std::cout << "age is type " << typeid (age).name () << std::endl; std::cout << "name is type " << typeid (name).name () << std::endl; std::cout << "height is type " << typeid (height).name () << std::endl; std::cout << "weight is type " << typeid (wight).name () << std::endl; }static void autoPointer () { auto age = new int (10 ); auto name = "Yt" ; auto height = new float (160.0f ); auto wight = new double (72.0 ); std::cout << "age is type " << typeid (age).name () << std::endl; std::cout << "name is type " << typeid (name).name () << std::endl; std::cout << "height is type " << typeid (height).name () << std::endl; std::cout << "weight is type " << typeid (wight).name () << std::endl; }static void newVersionFor () { int ids[] = {1 , 2 , 3 , 4 , 5 }; std::cout << "new version" ; for (auto v : ids) { std::cout << v << " " ; } std::cout << std::endl; std::cout << "old version" ; for (int i = 0 ; i < sizeof (ids) / sizeof (ids[0 ]); ++i) { std::cout << ids[i] << " " ; } std::cout << std::endl; std::vector<int > group; for (int i = 0 ; i < 4 ; ++i) group.push_back (i); for (std::vector<int >::size_type i = 0 , size = group.size (); i < size; ++i) { } std::cout << "iterator: " << std::endl; for (std::vector<int >::const_iterator iter = group.begin (); iter != group.end (); ++iter) { std::cout << *iter << " " ; } std::cout << std::endl; std::cout << "vector old version:" << std::endl; for (auto v : group) { std::cout << v << " " ; } std::cout << std::endl; std::cout << "vector new version:" << std::endl; for (auto &v : group) { v = 1 ; } for (const auto &v : group) { std::cout << v << " " ; } }class A { public : explicit A (int value) : m_value(value) { } private : int m_value; };static void newVersionConstruct () { A a (10 ) ; A b{3 }; int avector[] = {1 , 2 , 3 }; std::vector<int > bv; for (auto v : avector) bv.push_back (v); std::vector<int > cv = {1 , 2 , 3 }; std::vector<int > v {1 , 2 , 3 }; A c (true ) ; A d (false ) ; A e (1.0 ) ; }class B { public : B () : m_age (18 ), m_height (170 ), m_weight (75 ) {} explicit B (int age) : m_age(age), m_height(170 ), m_weight(75 ) { } B (int age, int height) : m_age (age), m_height (height) {} int age () const { return m_age; } int height () const { return m_height; } int weight () const { return m_weight; } private : int m_age; int m_height; int m_weight; };class NewB { public : NewB () {} explicit NewB (int age) : m_age { age} {} NewB (int age, int height) : m_age{age}, m_height {height} {} int age () const { return m_age; } int height () const { return m_height; } int weight () const { return m_weight; } void p () const { std::cout << m_value << " " << m_fightValue;} private : int m_age = 18 ; int m_height = 170 ; int m_weight = 75 ; int m_value{}; double m_fightValue{}; };static void defaultInitValue () { B a (10 , 20 ) ; NewB b (10 , 20 ) ; std::cout << "Old a age is" << a.age () << "height " << a.height () << " wight " << a.weight () << std::endl; std::cout << "New b age is" << b.age () << "height " << b.height () << " wight " << b.weight () << std::endl; b.p (); }static void leftRefAndRightRef () { int a = 10 ; int &refA = a; const int &constRefA = a; std::cout << " a" << a << " ref of a " << refA << " const ref a " << constRefA << std::endl; const int &constRefB = 10 ; std::cout << "different version const ref " << constRefB << std::endl; int &&rrB = 20 ; const int &&crrB = 20 ; rrB = 30 ; std::cout << " right ref of b " << rrB << " const right ref b " << crrB << std::endl; int b = 20 ; int &&newRRB = std::move (b); const int &&cNewRRB = std::move (b); std::cout << " b " << b << " right ref of be " << newRRB << "const right ref b " << cNewRRB << std::endl; std::cout << "address " << &b << " ref " << &newRRB << " c ref " << &cNewRRB << std::endl; }
C++11智能指针 目前c++ 的4种指针
auto_ptr c++98 智能指针,使用了
shared_ptr //共享指针
unique_ptr //只能由一个使用者使用
weaked_ptr //与share_ptr搭配使用
shared_patr 实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 #include <iostream> #include <memory> static void interfaceOfSharedPtr () ;int main (void ) { interfaceOfSharedPtr (); return 0 ; }class Object { public : Object (int id) : m_id (id) { std::cout << "init obj " << m_id << std::endl; }; ~Object () { std::cout << "bye bye " << m_id << std::endl; } int id () const { return m_id; } private : int m_id = 0 ; };using ObjectPtr = std::shared_ptr<Object>;void print (ObjectPtr obj) { std::cout << "count " << obj.use_count () << " id " << obj->id () << std::endl; }void printRef (const ObjectPtr &obj) { std::cout << "ref count " << obj.use_count () << "id " << obj->id () << std::endl; }static void interfaceOfSharedPtr () { ObjectPtr null; std::cout << "ref count is " << null.use_count () << std::endl; ObjectPtr obj (new Object(1 )) ; std::cout << "ref count is " << obj.use_count () << std::endl; ObjectPtr obj2 (obj) ; std::cout << "ref count is " << obj2.use_count () << std::endl; ObjectPtr obj3 = obj; std::cout << "ref count is " << obj.use_count () << std::endl; obj2.reset (); std::cout << "ref count is " << obj.use_count () << std::endl; ObjectPtr obj4; obj3.swap (obj4); std::cout << "obj4 ref count is " << obj4.use_count () << std::endl; std::swap (obj3, obj4); std::cout << "obj4 ref count is " << obj4.use_count () << std::endl; auto p = obj.get (); if (p) { std::cout << "id is" << p->id () << std::endl; } if (obj) { std::cout << "p id is " << obj->id () << std::endl; std::cout << "ref id is " << (*obj).id () << std::endl; } obj4 = nullptr ; std::cout << "only one hold ptr " << obj.unique () << std::endl; std::cout << "judge differnt: " << std::endl; std::cout << "use_count: " << obj.use_count () << std::endl; printRef (obj); print (obj); std::cout << "use_count: " << obj.use_count () << std::endl; }void deleterOfObject (Object *obj) { if (obj) std::cout << "delete obj " << obj->id () << std::endl; delete obj; }void useDeleter () { ObjectPtr obj (new Object(2 ), deleterOfObject) ; ObjectPtr obj2 = obj; }
weak_ptr c++智能指针-shared_ptr的尴尬-诞生weak_ptr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 #include <iostream> #include <memory> #include <cassert> class Parent ; using ParentPtr = std::shared_ptr<Parent>;typedef std::weak_ptr<Parent> WeakParentPtr;class Child { public : WeakParentPtr father; Child () { std::cout << "Child!!" << std::endl; } ~Child (); };typedef std::shared_ptr<Child> ChildPtr;typedef std::weak_ptr<Child> WeakChildPtr;class Parent { public : Parent () { std::cout << "Parent!!" << std::endl; } ChildPtr son; void print () const { std::cout << "use_count: " << this ->son.use_count () << std::endl;} ~Parent (); };class Object { public : Object (int id) : m_id (id) { std::cout << "init obj " << m_id << std::endl; }; ~Object () { std::cout << "bye bye " << m_id << std::endl; } int id () const { return m_id; } private : int m_id = 0 ; };using ObjectPtr = std::shared_ptr<Object>; Child::~Child () { std::cout << "bye child!" << std::endl; } Parent::~Parent () { std::cout << "bye parent!" << std::endl; }void testParentAndChild () { ParentPtr p (new Parent()) ; ChildPtr c (new Child()) ; p->son = c; p->print (); c->father = p; }void sharedPtrWithWeakPtr () { ObjectPtr obj (new Object(1 )) ; typedef std::weak_ptr<Object> WeakObjectPtr; WeakObjectPtr weakObj (obj) ; WeakObjectPtr weakObj2 (obj) ; std::cout << "obj use count is " << obj.use_count () << std::endl; { auto p = weakObj.lock (); std::cout << "expired: " << weakObj.expired () << std::endl; if (p) { std::cout << p.unique () << std::endl; }else { } } obj.reset (); std::cout << "endl;" ; auto p2 = weakObj.lock (); obj.reset (new Object (2 )); { auto p = weakObj.lock (); if (p) { assert (false ); }else { std::cout << "changed!" << std::endl; } } std::cout << "expired: " << weakObj.expired () << std::endl; }int main (void ) { testParentAndChild (); return 0 ; }
shared_ptr储存this指针多次析构问题 enable_shared_from_this解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include <iostream> #include <memory> #include <cassert> class Parent ;typedef std::shared_ptr<Parent> ParentPtr;typedef std::weak_ptr<Parent> WeakParentPtr;class Child : public std::enable_shared_from_this<Child> { public : WeakParentPtr father; ~Child (); Child (); void checkRelation () ; };typedef std::shared_ptr<Child> ChildPtr;typedef std::weak_ptr<Child> WeakChildPtr;class Parent : public std::enable_shared_from_this<Parent> { public : WeakChildPtr son; ~Parent (); Parent (); void checkRelation () ; };void handleChildAndParentRef (const Parent &p, const Child &c) { if (c.father.lock ().get () == &p && p.son.lock ().get () == &c) { std::cout << "right relation" << std::endl; }else { std::cout << "oop!!!!!!" << std::endl; } }void handleChildAndParent (const ParentPtr &p, const ChildPtr &c) { assert (c); assert (p); if (c->father.lock () == p && p->son.lock () == c) { std::cout << "right relation" << std::endl; }else { std::cout << "oop!!!!!!" << std::endl; } } Child::Child () { std::cout << "hello child" << std::endl; } Child::~Child () { std::cout << "bye child" << std::endl; } Parent::Parent () { std::cout << "hello parent" << std::endl; } Parent::~Parent () { std::cout << "bye parent" << std::endl; }void Parent::checkRelation () { auto ps = son.lock (); if (ps) { handleChildAndParent (shared_from_this (), ps); } std::cout << "after call checkRelation" << std::endl; }void Child::checkRelation () { }void testParentAndChild () { ParentPtr p (new Parent()) ; ChildPtr c (new Child()) ; p->son = c; c->father = p; p->checkRelation (); }static void interfaceOfSharedPtr () ;static void sharedPtrWithWeakPtr () ;static void uniquePtr () ;int main (void ) { testParentAndChild (); return 0 ; }
unique_ptr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 #include <iostream> #include <memory> #include <cassert> class Object ;typedef std::unique_ptr<Object> UniqueObjectPtr;using ObjectPtr = std::shared_ptr<Object>;void print (const UniqueObjectPtr& obj) {}class Object { public : Object (int x) : m_id (x) { std::cout << "Hello Obj" << std::endl; }; ~Object () { std::cout << "Bye Obj" << std::endl; }; int id () { return m_id; } private : int m_id = 0 ; };void transfer (UniqueObjectPtr obj) { std::cout << obj->id () << std::endl; }void uniquePtr () { UniqueObjectPtr obj { new Object (1 ) }; auto p = obj.get (); if (p) { } if (obj) { } std::cout << p->id () << " " << obj->id () << " " << (*obj).id () << " " << std::endl; print (obj); p = obj.release (); std::cout << "release: unique_ptr" << std::endl; delete p; obj.reset (new Object (2 )); transfer (std::move (obj)); assert (obj == nullptr ); obj.reset (new Object (3 )); ObjectPtr sharedObj (std::move(obj)) ; assert (obj == nullptr ); }int main (void ) { uniquePtr (); return 0 ; }
智能指针总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <iostream> #include <memory> #include <cassert> void sharedPtrNotice () ;class Parent ;typedef std::shared_ptr<Parent> ParentPtr;typedef std::weak_ptr<Parent> WeakParentPtr;class Child : public std::enable_shared_from_this<Child> { public : WeakParentPtr father; Child (); ~Child (); };class Object { public : Object (int x) : m_value (x) { } private : int m_value = 0 ; };using ObjectPtr = std::shared_ptr<Object>;void sharedPtrNotice () { ObjectPtr obj5 = std::make_shared <Object>(3 ); Object obj6 (4 ) ; std::unique_ptr<Object> puObj (new Object(1 )) ; std::shared_ptr<Object> psObj = std::make_shared <Object>(3 ); }int main (void ) { return 0 ; }