C++(14)--面向对象

面向对象

  • 1.面向对象编程(难点)
  • 2.类和对象
    • demo1:地主类的实现版本1
    • demo2:地主类的实现版本2
  • 3.访问修饰符
    • demo3:外部修改成员变量不安全(版本3)
    • demo4: 使用封装防止直接修改成员变量(版本3)
    • demo5:进一步封装:设置/获取名字,修改积分(版本4)
  • 4.构造函数与析构函数(重点)
    • 4.1默认构造函数
      • demo6: 使用构造函数进行成员变量的初始化
    • 4.2 带参构造函数
      • demo7:学生类构建--堆内存对象/栈内存对象
    • 4.3 析构函数
      • demo8:学生类析构函数演示
  • 5.this指针(重点)
    • demo9:学霸返回引用的使用

《老九学堂C++课程》《C++ primer》学习笔记。《老九学堂C++课程》详情请到B站搜索《老九零基础学编程C++入门》
-------------简单的事情重复做,重复的事情用心做,用心的事情坚持做(老九君)---------------

1.面向对象编程(难点)

oop: object oriented programming

何为面向对象:基于对象的概念,以对象为中心,以类和继承为构造机制,来认识、理解、刻画客观世界;涉及构建相应的软件系统(模拟现实)

1.对象–有数据和容许的操作组成的封装体,与客观实体有直接的对应关系(属性和方法的集合)

面向对象不是某一种语言的特性,而是一种编程思想。原来面向过程代码超过10W行就会难管理,原来有因为飞机控制程序中一个,写成.号造成的空难。

举个粒子:斗地主游戏的开发
面向过程:一步一步来,很多很多的过程函数:开始游戏-洗牌-发牌-显示手牌…-输出结果

面向对象:
1.游戏参与者,行为模式是相同的–玩家对象,相同的属性和行为;
2.进行游戏的场景–牌桌对象,负责现实游戏的界面及内容;
3.游戏规则系统–裁判对象,负责判定牌面、输赢;

小结:
1.面向过程编程,首先考虑要遵循的步骤,然后考虑如何表示这些数据
2.oop编程,首先会考虑数据,包括数据的表示和数据的使用

2.类和对象

面向对象的编程流程:
1.抽象:从具体食物抽取共同的本质特征,【处理复杂问题的技巧–简化、抽象】

地主对象:外表特征–胖,留两撇胡子,两颗大金牙;行为特点–先出牌,多摸三张牌

2.用类封装:将抽象转换为用户定义类型的工具,将数据表示和操作数据的方法组合成一个整体。类的实例成为对象(对象的集合就是类,还可以这么理解:类就是对象模版),类中的变量和函数称为成员。

地主类:
成员变量:名称、积分、手牌
成员函数:摸牌、出牌、产看积分

类的声明:使用class/struct 关键字声明,
两者的区别:使用class声明的类默认成员是私有的(private),struct声明的类默认成员是共有的(public)。
推荐使用class声明类;struct声明结构,只包含数据POD,老式数据

class 类名{};
struct 类名{};

头文件中声明类(.h/.cpp),专门有一个类名.cpp文件实现类。

demo1:地主类的实现版本1

–LandOwnerV1.cpp 文件中既声明又实现,包含main 函数的main.cpp文件中调用

// mian.cpp 文件
#include "LandOwnerV1.cpp"
int main(){// 类,对象实验LandOwnerV1 landOwner1; // 声明了一个LandOwner1类型的变量landowner1// 调用对象的成员方法, 不能直接使用对象的私有成员// landOwner1.cards[0] = 0; 'cards' is a private member of 'LandOwnerV1' ,直接报错landOwner1.TouchCard(100);return 0;
}
// LandOwnerV1.cpp 文件既声明又实现
#include <iostream>
using namespace std;
// .hpp 一般包含实现的内联函数,通常用于模版类这种声明与实现共存的情况
// 建议:只要不是纯模版,一律使用.h 作为头文件后缀, .cpp 作为函数的实现文件
// 地主类的声明、实现
class LandOwnerV1 {private:string name;	// 名称long score;		// 积分int cards[20];	// 手牌数组public :LandOwnerV1() {};	// 默认构造函数~LandOwnerV1() {};	// 默认析构函数void TouchCard(int CardCount){// 暂时省略函数实现cout << name << "摸了" << CardCount << "张牌" << endl;}void ShowScore(){cout << name << "当前的积分为:" << score << endl;}};

输出

摸了100张牌

demo2:地主类的实现版本2

–LandOwnerV2.h中声明,LandOwnerV2.cpp中实现,main.cpp文件中调用

成员函数没有调用成功

// mian.cpp 文件
#include "LandOwnerV2.h"  // 关注.h 文件
using namespace std;
int main(){LandOwnerV2 landowner2;landowner2.name = "小明";//landowner2.TouchCard(20);  // 这个方法实现不了cout << landowner2.name << endl;return 0;
}
// LandOwnerV2.h
#include <iostream>
using namespace std;
// .hpp 一般包含实现的内联函数,通常用于模版类这种声明与实现共存的情况
// 建议:只要不是纯模版,一律使用.h 作为头文件后缀, .cpp 作为函数的实现文件
// 地主类的声明class LandOwnerV2 {private:long score;		// 积分int cards[20];	// 手牌数组public :string name;	// 名称LandOwnerV2();	// 构造函数声明~LandOwnerV2();	// 析构函数声明 void TouchCard(int);		// 声明摸牌函数void PlayCard(int);		    // 声明出牌函数void ShowScore();			// 声明产看积分函数
};
// LandOwnerV2.cpp
#include <iostream>
#include "LandOwnerV2.h"
using namespace std;LandOwnerV2::LandOwnerV2()
{//ctor
}void LandOwnerV2::TouchCard(int CardCount){cout << name << "摸了" << CardCount << "张牌" << endl;
}
void LandOwnerV2::ShowScore(){cout << name << "当前的积分为:" << score << endl;
}LandOwnerV2::~LandOwnerV2()
{//dtor
}

(xcode 太不友好了,写到类分文件时就无法编译,弃坑!转向CLION,友好很多。)

3.访问修饰符

public: 修饰的成员在任意地方都可以访问
private:修饰的成员只能在类中或者友元函数中访问, 私有属性可以习惯性在名字前面加一个_
protected:修饰的成员可以在类中函数、子类函数、友元函数中访问

(数据隐藏:不希望别人随意操作,对应的操作叫做封装)

在修饰关键字放在类定义的关键字中,加冒号,无修饰关键字默认为private

class 类名{
修饰符:成员类标;
};

demo3:外部修改成员变量不安全(版本3)

非私有成员,会被直接修改–修改地主积分

// mian.cpp 文件
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
int main(){// 访问修饰符的实验LandOwnerv3 landOwner3;landOwner3.name = "巴依老爷";// 修改地主积分landOwner3.score = 100;landOwner3.ShowScore(landOwner3.score);return 0;
}
// LandOwnerv3.h 文件
// Created by 陈莹莹 on 2021/1/28.
#include <iostream>
#ifndef HELLOWORLD_LANDOWNERV3_H
#define HELLOWORLD_LANDOWNERV3_H
using namespace std;
class LandOwnerv3 {int cards[20];	// 手牌数组
public :string name;long score;		// 积分LandOwnerv3();	// 构造函数声明, 没有返回值~LandOwnerv3();	// 析构函数声明void TouchCard(int);		// 声明摸牌函数void PlayCard(int);		    // 声明出牌函数void ShowScore(int);			// 声明产看积分函数
};
#endif //HELLOWORLD_LANDOWNERV3_H
// LandOwnerv3.cpp 文件
// Created by 陈莹莹 on 2021/1/28.
// 用来演示封装的基本概念
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
LandOwnerv3::LandOwnerv3()
{//ctor
}
void LandOwnerv3::ShowScore(int score){cout << name     << "当前的积分为:" << score << endl;
}LandOwnerv3::~LandOwnerv3()
{//dtor
}

输出:

巴依老爷当前的积分为:100

demo4: 使用封装防止直接修改成员变量(版本3)

但是如此操作使得大家可以随意修改这个积分,有一些不合理的积分就会出现。为了解决积分被赋值为不合理的情况,需要将成员变量score进行封装(使用方法来实现对成员的封装)
demo4:类封装概念,get/set方法

// mian.cpp 文件
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
int main(){// 访问修饰符的实验LandOwnerv3 landOwner3;landOwner3.name = "巴依老爷";// 修改地主积分landOwner3.SetScore(-100);landOwner3.ShowScore();return 0;
}
// LandOwnerv3.h 文件
// Created by 陈莹莹 on 2021/1/28.
#include <iostream>
#ifndef HELLOWORLD_LANDOWNERV3_H
#define HELLOWORLD_LANDOWNERV3_H
using namespace std;
class LandOwnerv3 {long score;		// 积分int cards[20];	// 手牌数组
public :string name;LandOwnerv3();	// 构造函数声明, 没有返回值~LandOwnerv3();	// 析构函数声明void TouchCard(int);		// 声明摸牌函数void PlayCard(int);		    // 声明出牌函数void ShowScore();			// 声明产看积分函数// 定义成内联函数即可void SetScore(long lScore){// 通过条件判断封装了score的赋值过程if(lScore < 0){score = 0;}else{score = lScore;}}
};
#endif //HELLOWORLD_LANDOWNERV3_H
// LandOwnerv3.cpp 文件
// Created by 陈莹莹 on 2021/1/28.
// 用来演示封装的基本概念
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
LandOwnerv3::LandOwnerv3()
{//ctor
}
void LandOwnerv3::ShowScore(){cout << name     << "当前的积分为:" << score << endl;
}LandOwnerv3::~LandOwnerv3()
{//dtor
}

输出:

巴依老爷当前的积分为:0

demo5:进一步封装:设置/获取名字,修改积分(版本4)

// mian.cpp 文件
#include <iostream>
#include "LandOwnerv41.h"
using namespace std;
int main(){// 访问修饰符的实验LandOwnerv41 landOwner4;landOwner4.SetName("巴依老爷");cout << landOwner4.GetName() << endl;// 修改地主积分landOwner4.SetScore(-100);landOwner4.ShowScore();return 0;
}
// LandOwnerv41.h 文件
// Created by 陈莹莹 on 2021/1/29.
#ifndef HELLOWORLD_LANDOWNERV41_H
#define HELLOWORLD_LANDOWNERV41_H#include <iostream>
using namespace std;
class LandOwnerv41 {long score;		// 积分int cards[20];	// 手牌数组string name;
public :LandOwnerv41();	// 构造函数声明, 没有返回值~LandOwnerv41();	// 析构函数声明void TouchCard(int);		// 声明摸牌函数void PlayCard(int);		    // 声明出牌函数void ShowScore();			// 声明产看积分函数// 定义成内联函数即可void SetScore(long lScore){// 通过条件判断封装了score的赋值过程if(lScore < 0){score = 0;}else{score = lScore;}}string GetName(){return name;}void SetName(string lName){name = lName;}};
#endif //HELLOWORLD_LANDOWNERV41_H
// LandOwnerv41.cpp 文件
// Created by 陈莹莹 on 2021/1/29.
#include "LandOwnerv41.h"
#include <iostream>
using namespace std;
LandOwnerv41::LandOwnerv41()
{//ctor
}
void LandOwnerv41::ShowScore(){cout << name     << "当前的积分为:" << score << endl;
}LandOwnerv41::~LandOwnerv41()
{//dtor
}

4.构造函数与析构函数(重点)

构造函数:与类同名,没有返回值
构造函数的作用:给编译器看的,编译器在对象被创建时,为对象分配内存空间,并自动调用构造函数以完成成员的初始化
构造函数的种类:无参数构造,一般构造(重载构造),拷贝构造。(本节主要介绍:无参构造,一般构造)

4.1默认构造函数

demo6: 使用构造函数进行成员变量的初始化

// mian.cpp 文件
//演示构造函数
#include "LandOwnerv41.h"
using namespace std;
int main(){LandOwnerv41 landOwnerv4;   // 省略了默认构造LandOwnerv41 landOwnerv4();   // 标准写法,但是不调用默认构造函数了?--不输出内容了return 0;
}
// LandOwnerv41.h 文件
// 与demo5一致
// LandOwnerv41.cpp 文件
// Created by 陈莹莹 on 2021/1/29.
//
#include "LandOwnerv41.h"
#include <iostream>
#include <memory.h>
using namespace std;
LandOwnerv41::LandOwnerv41()
{cout << "LandOwnerV41的无参数构造函数(默认构造)被调用!" << endl;name = "默认地主";score = 0;//将用户的手牌数组初始化为0memset(cards, 0, sizeof(cards)/sizeof(cards[0]));cout << "初始化的结果如下:" << endl;cout << "名字:" << name << endl;cout << "积分:" << score << endl;cout << "手牌数组:" ;for(int i=0; i < sizeof(cards)/sizeof(cards[0]); i++){cout << cards[i] << "\t";}cout << endl;
}
void LandOwnerv41::ShowScore(){cout << name     << "当前的积分为:" << score << endl;
}LandOwnerv41::~LandOwnerv41()
{//dtor
}

为啥手牌数组的初始化不是全为0?

LandOwnerV41的无参数构造函数(默认构造)被调用!
初始化的结果如下:
名字:默认地主
积分:0
手牌数组:0	0	0	0	0	0	0	0	-375207560	32766	-375207584	32766	0	1	0	0	0	0	0	0	

默认构造显式写法:

LandOwnerV4() = default;

注意:
1.如果创建的类中未书写任何构造函数,系统会自动生成默认的无参构造函数(函数为空,什么都不做)
2.如果书写了构造函数,系统不会自动生成默认构造函数,如果希望有一个这样的无参数构造函数,需要自己显示书写LandOwnerV4() = default;

4.2 带参构造函数

语法:

类名::构造(类型1 参数1, 类型2 参数2, ....){// 相关初始化方法
}

demo7:学生类构建–堆内存对象/栈内存对象

1.栈内存中的对象(类似于函数声明),
具体对象由系统创建并释放,不用担心内存泄露。
声明周期只在声明区域的大括号内。
栈内存的优势存取速度快(仅次于寄存器),缺点栈内存中的数据大小生存期是确定的,缺乏灵活性。

自定义类型名 对象名;
Student stu();
Student stu;

2.堆内存中的对象(需要new关键字)
p_stu1是指针,必须使用delete释放
使用灵活可以赋给全局变量,可以把对象作为函数的返回值
用好了

Student *p_stu1= new Student();
Student *p_stu2= new Student();
auto *p_stu3= new Student(); // auto 自动类型判断,不推荐使用,sizeof 会报错

类对象推荐放在堆内存中,即使用new来创建对象。

// mian.cpp 文件
#include <iostream>
#include "Student.h"
using namespace std;
int main(){// 演示构造函数,实质就是函数重载Student stu1;Student stu2("马化腾","普通家庭");     // 在栈内存中直接分配空间,速度块// 如果构造函数中只有一个参数,且单参数构造函数只有一个,可以直接使用赋值操作进行初始化// Student stu4 = 45stu2.showInfo();// 学生指针类型, 使用new 分配内存空间Student * stu5 = new Student("杰克马", "毁创阿里");  // 在堆内存中分配空间// 类指针访问方法要使用 ->stu5 ->showInfo();return 0;
}

输出结果:

默认构造函数
设置带参构造
普通家庭马化腾
设置带参构造
毁创阿里杰克马
// Student.h 文件
//
// Created by 陈莹莹 on 2021/2/2.
//
#ifndef HELLOWORLD_STUDENT_H
#define HELLOWORLD_STUDENT_H
#include <iostream>
using namespace std;class Student {
private:string m_name;string m_desc;int m_age;
public:Student();          // 默认构造函数Student(string, string);~Student();void showInfo();};
#endif //HELLOWORLD_STUDENT_H
// Student.cpp 文件
//
// Created by 陈莹莹 on 2021/2/2.
//
#include <iostream>
#include "Student.h"
using namespace std;Student::Student() {cout << "默认构造函数" << endl;
}
//Student::Student(string name, string desc){
//    // 参数列表不同,函数重载
//    m_name = name;
//    m_desc = desc;
//    cout << "设置带参构造" << endl;
//}
//初始化参数列表的写法,和上上面的带参数构造方法完全相同
Student::Student(string name, string desc):m_name(name), m_desc(desc){cout << "设置带参构造" << endl;
};void Student::showInfo() {cout << m_desc << m_name << endl;
}
Student::~Student() {}

4.3 析构函数

对象销毁时自动调用的特殊成员函数, 析构函数一般用来完成清理工作。
析构函数名称在类名前加一个~,析构函数没有参数,只能有一个

在栈内存中构造的对象,在栈区(mian函数)销毁时,类对象会被自动销毁。在堆内存中构建的类对象,需要手动释放。

在析构函数内部需要释放(delete)掉在构造函数中手动分配(new)的空间(对象内部的成员变量)。

1.析构函数用来释放对象使用的资源,并销毁对象的非static数据成员.
2.无论何时一个对象被销毁,都会自动调用析构函数(隐式析构)

demo8:学生类析构函数演示

类对象推荐放在堆内存中,即使用new来创建对象。

// mian.cpp 文件
#include <iostream>
#include "Student.h"
using namespace std;
int main(){// 演示构造函数,实质就是函数重载Student stu1;Student stu2("马化腾","普通家庭");     // 在栈内存中直接分配空间,速度块// 如果构造函数中只有一个参数,且单参数构造函数只有一个,可以直接使用赋值操作进行初始化// Student stu4 = 45stu2.showInfo();// 学生指针类型, 使用new 分配内存空间Student * stu5 = new Student("杰克马", "毁创阿里");  // 在堆内存中分配空间// 类指针访问方法要使用 ->stu5 ->showInfo();return 0;
}

输出结果:

默认构造函数
设置带参构造
普通家庭马化腾
设置带参构造
毁创阿里杰克马
杰克马被释放     # 杰克马为啥被释放了?
马化腾被释放
被释放
// Student.h 文件
// 与demo7一样
// Student.cpp 文件
//
// Created by 陈莹莹 on 2021/2/2.
//
#include <iostream>
#include "Student.h"
using namespace std;Student::Student() {cout << "默认构造函数" << endl;
}
//Student::Student(string name, string desc){
//    // 参数列表不同,函数重载
//    m_name = name;
//    m_desc = desc;
//    cout << "设置带参构造" << endl;
//}
//初始化参数列表的写法,和上上面的带参数构造方法完全相同
Student::Student(string name, string desc):m_name(name), m_desc(desc){cout << "设置带参构造" << endl;
};void Student::showInfo() {cout << m_desc << m_name << endl;
}
Student::~Student() {cout << m_name << "被释放" << endl;
}

5.this指针(重点)

(类似于于python中的self,在python中显式传递self参数)
每个成员函数(包括构造函数和析构函数)都有一个this指针。this指针指向调用对象,可以通过this关键字访问当前对象的成员。

  1. 访问成员变量:this -> 成员名;
  2. 访问成员函数:this -> 函数名();

this 在成员函数执行前就已经创建,在析构函数之后被销毁。

->this 指针的类型为*const,为右值;(可以赋值)
->this指针本身不占用大小,并不是对象的一部分,用sizeof 测不出来大小
->this指针作用域在成员函数内部;
->this指针是类成员函数的第一个默认隐含参数,编译器自动维护传递,编写者不能显式传递。
->在类非静态成员函数中才可以使用this指针,其他任何函数都不可以(static是先于类实例存在的,this还没有创建)

this 返回当前对象的引用,太难用了-- Student & GetSuperScholars(Student &);

demo9:学霸返回引用的使用

//mian.cpp
#include <iostream>
#include "Student.h"
using namespace std;
int main(){Student *ptr_stu1 = new Student("迪丽热巴","微胖女孩");ptr_stu1->AddScore(78.9);ptr_stu1->AddScore(77.9);ptr_stu1->AddScore(72.9);ptr_stu1->AddScore(79.9);ptr_stu1->AddScore(800);ptr_stu1->showInfo();Student stu2("刘强东","不爱美人");stu2.AddScore(78.9);stu2.AddScore(77.9);stu2.AddScore(72.9);stu2.AddScore(79.9);stu2.AddScore(90);stu2.showInfo();//    Student scholar1 = stu2.GetSuperScholars(*ptr_stu1); 返回new出来的结果,接受的确实栈类型,矛盾,空间释放的时候会出问题
//    Student scholar2 = ptr_stu1->GetSuperScholars(stu2);Student &scholar1 = stu2.GetSuperScholars(*ptr_stu1);  //返回迪丽热巴的引用,Student &scholar2 = ptr_stu1->GetSuperScholars(stu2);  //返回迪丽热巴的引用cout << "学霸是" << scholar1.GetName() << "\t" << scholar2.GetName() << endl;delete ptr_stu1;return 0;//scholar1 栈内存中定义的,main 结束后会自动释放//scholar2 栈内存中定义的,main 结束后会自动释放
}
//Student.h
//
// Created by 陈莹莹 on 2021/2/2.
//
#ifndef HELLOWORLD_STUDENT_H
#define HELLOWORLD_STUDENT_H
#include <iostream>
using namespace std;class Student {
private:string m_name;string m_desc;int m_age;float *scores; // 学生的分数数组,在某次构造的时候进行初始化int scoreCount; // 学生成绩的个数public:Student();          // 默认构造函数Student(string, string);~Student();void showInfo();void InitScores(); // 初始化学生的成绩数组,默认分配一个元素空间void AddScore(float score);// 返回值是引用时,是非常危险的。this可以直接修改属性,建议在函数声明处加一个const,限制在该函数内部不能通过this指针修改属性,太麻烦了,要该的地方太多了Student & GetSuperScholars(Student &); //返回学霸对象// 参数处加const 保证不对该参数进行修改。float GetTotal();string GetName() {return m_name;}};#endif //HELLOWORLD_STUDENT_H
//Student.cpp
//
// Created by 陈莹莹 on 2021/2/2.
//
#include <iostream>
#include "Student.h"
using namespace std;Student::Student() {cout << "默认构造函数" << endl;InitScores();
}
//Student::Student(string name, string desc){
//    // 参数列表不同,函数重载
//    m_name = name;
//    m_desc = desc;
//    cout << "设置带参构造" << endl;
//}
//初始化参数列表的写法,和上上面的带参数构造方法完全相同
Student::Student(string name, string desc):m_name(name), m_desc(desc){cout << "设置带参构造" << endl;InitScores();
};void Student::showInfo() {cout << m_desc << m_name << endl;for(int i = 0; i < scoreCount-1; i++){cout << this->scores[i] << "\t";}cout << endl;
}
// C的类方法写(我这么写编译不过)
//void MyShow(const Student* this){
//    this->
//}
void Student::InitScores() {this -> scores = new float [1];this -> scoreCount = 1;
}
void Student::AddScore(float score) {this -> scores[this->scoreCount -1] = score;// 1. 创建一个新数组,分配scoreCount+1 个空间// 2. 复制愿数组中的内容到新数组中// 3. scoreCount++// 4. scores指向新数组float *newScores = new float [scoreCount + 1];float *oldScores = scores;memcpy(newScores, scores, sizeof(float) * scoreCount);scoreCount++;scores = newScores;delete oldScores;    // 删除原来的指针
}
Student & Student::GetSuperScholars(Student &otherstu){// otherstu 要对比的另一学生对象// 返回总分比较大的那个学生对象// 分别计算两个学生的总分if(this->GetTotal() > otherstu.GetTotal()){return *this;}else{return otherstu;}}
float Student::GetTotal(){float sum = 0;for(int i = 0; i < scoreCount; i++){sum += scores[i];}return sum;}
Student::~Student() {cout << m_name << "被释放" << endl;delete this -> scores;}

输出

设置带参构造
微胖女孩迪丽热巴
78.9	77.9	72.9	79.9	800	
设置带参构造
不爱美人刘强东
78.9	77.9	72.9	79.9	90	
学霸是迪丽热巴	迪丽热巴
迪丽热巴被释放
刘强东被释放

小结:类就是自己定义的数据类型,对象就是变量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444808.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

终于,我读懂了所有Java集合——map篇(多线程)

多线程环境下的问题 1.8中hashmap的确不会因为多线程put导致死循环&#xff08;1.7代码中会这样子&#xff09;&#xff0c;但是依然有其他的弊端&#xff0c;比如数据丢失等等。因此多线程情况下还是建议使用ConcurrentHashMap。 数据丢失&#xff1a;当多线程put的时候&…

system函数的返回值和执行脚本的返回值

1、先统一两个说法&#xff1a;&#xff08;1&#xff09;system返回值&#xff1a;指调用system函数后的返回值&#xff0c;比如上例中status为system返回值&#xff08;2&#xff09;shell返回值&#xff1a;指system所调用的shell命令的返回值&#xff0c;比如上例中&#x…

OJ汇总

国内&#xff1a;&#xff08;一下排名不分先后&#xff09; 浙江大学&#xff08;ZJU&#xff09;&#xff1a;http://acm.zju.edu.cn/ 北京大学&#xff08;PKU&#xff09;&#xff1a;http://acm.pku.edu.cn/JudgeOnline/ 同济大学&#xff08;TJU&#xff09;&#xff1a;…

C++(15)--面向对象编程实践-欢乐斗地主(vector的花式输出)

面向对象编程实践-欢乐斗地主《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)---------------要求&#xff1a;实现录入及…

Google Protobuf 使用介绍

直接在 www.google.com.hk 上搜索google protobuf 后下载官方版本。 官方版本支持C\Java\Python三门语言。 还有很多非官方的语言版本支持&#xff0c;如C\NET(C#/Vb.net)\Flex(AS3)等. 要通信&#xff0c;必须有协议&#xff0c;否则双方无法理解对方的码流。在protobuf中&…

epoll的再次认识

使用mmap加速内核与用户空间的消息传递。 这 点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很 重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关…

leetcode82. 删除排序链表中的重复元素 II

给定一个排序链表&#xff0c;删除所有含有重复数字的节点&#xff0c;只保留原始链表中 没有重复出现 的数字。 示例 1: 输入: 1->2->3->3->4->4->5 输出: 1->2->5 示例 2: 输入: 1->1->1->2->3 输出: 2->3 思路&#xff1a;判断n…

C++(16)--运算符重载(自定义Integer类)

运算符重载1.运算符重载--重点2.友元函数--难点(流运算符重载)《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》 -------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)--------…

反应器组件 ACE_Reactor

6.1 反应器组件 ACE_Reactor反应器的基本原理是: 针对关心的某个事件写一个事件处理器(event_handler). 将该事件处理器登记到反应器中(同时指明关心的事件). 然后反应器会自动检测事件的发生. 并调用预先登记的事件处理器中的回调函数. 所以ACE Reactor 框架的责任&#x…

C++(17)--详解const

详解const《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)---------------1.const修饰成员变量 2.const修饰函数参数 3.c…

cppcheck的安装和使用

首先从这里下载linux版本的:http://sourceforge.net/projects/cppcheck/files/cppcheck/ 然后下载对应的版本,解压,之后安装: 编译: g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp 安装: make install

leetcode24 两两交换链表中的节点

给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 思路&#xff1a;这一看就是个递归定义&…

再议指针和引用的一些事情吧

关于指针和引用一直是学习C++的同学们争论的焦点,什么时候用指针,什么时候用引用,还有怎么引用数组,这么用指针访问数组,以及初始化的问题。 不过有一些文章我在很早就已经写过,但是由于当时时间不充分,自己也都是随性写的,可以参看以前我的一个文章:http://blog.csd…

C++(18)--复制构造函数

复制构造函数《老九学堂C课程》《C primer》学习笔记。《老九学堂C课程》详情请到B站搜索《老九零基础学编程C入门》-------------简单的事情重复做&#xff0c;重复的事情用心做&#xff0c;用心的事情坚持做(老九君)---------------包装基本类&#xff0c;封装一些算法。 需求…

lua与C++粘合层框架

一. lua调用C 在lua中是以函数指针的形式调用函数, 并且所有的函数指针都必须满足如下此种类型: typedef int (*lua_CFunction) (lua_State *L);   也就是说, 偶们在C中定义函数时必须以lua_State为参数, 以int为返回值才能被Lua所调用. 但是不要忘记了, 偶们的lua_State是…

leetcode147 对链表进行插入排序

丢人&#xff0c;我就是按插入排序老老实实写的啊。。。。 别人肯定map了hhh。 对链表进行插入排序。 插入排序的动画演示如上。从第一个元素开始&#xff0c;该链表可以被认为已经部分排序&#xff08;用黑色表示&#xff09;。 每次迭代时&#xff0c;从输入数据中移除一个…

PaperNotes(13)-Conditional Image Generation with PixelCNN Decoders

conditional Image generation with PixelCNN DecodersICML的best paperpixel cnn 属于完全可见的信念网络&#xff0c;需要对 概率密度 建模。给定图像数据x&#xff0c;想要对概率分布p(x)建模。概率分布p(x)可以看做&#xff0c;每一像素分布同时作用结果的一个联合分布。一…

Expression : invalid operator 解决方法

从技术上说&#xff0c;用于排序关联容器的比较函数必须在它们所比较的对象上定义一个“严格的弱序化(strict weak ordering)”。&#xff08;传给sort等算法的比较函数也有同样的限制&#xff09;,就是两个对象比大小或先后的规则&#xff0c;比如两个 string对象比大小的规则…

leetcode23 合并K个排序链表

合并 k 个排序链表&#xff0c;返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 思路&#xff1a;把初始的每一个链表当成数组中的一个数&#xff0c;做…

Xcode LaunchImage 载入界面大小设置

iPhone Portrait iOS 8-Retina HD 5.5 (12422208) @3x iPhone Portrait iOS 8-Retina HD 4.7 (7501334) @2x iPhone Portrait iOS 7,8-2x (640960) @2x iPhone Portrait iOS 7,8-Retina 4 (6401136) @2x iPhone Portrait iOS 5,6-1x (320480) @1x iPhone Portrait iO…