c++学习笔记(二)
1. C++内存布局分为几个区域,各自具备什么特点?
分为
内核区: Kernel Space User code CANNOT read from nor write
to these address, doing so result in a Segmentation Fault.
堆区、
栈区、
数据段{
【(全局静态区/全局变量---->bss segment)】
Uninitialized static variables, filed with zero,
【静态变量(data segment)】
Static Variables initialized by the programmer.
【只读段 /文字常量区 代码段区 text segemnt】
Store the binary image of the process.
}
2. 当定义类时,编译器会为类自动生成哪些函数?
这些函数各自都有什么特点?
默认构造函数和复制构造函数
默认构造函数:当没有定义一个默认构造函数时,系统会自动的给出一个默认构造函数
复制构造函数:
3. 什么是浅拷贝, 什么是深拷贝?
浅拷贝:复制的只是要拷贝数据地址,没有拷贝数据内容
深拷贝:这是申请一块新的内存地址,将原有的内容放到一个新申请的地址空间中去
4. 实现一个自定义的String类,保证main函数对正确执行
class String
{
public:
String();
String(const char *pstr);
String(const String & rhs);
String & operator=(const String & rhs);
~String();
void print();
private:
char * _pstr;
};
string实现
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;
class String
{
public:
String():_pstr(nullptr){
//要给char *_pstr;赋予一个NULL
cout << "_pstr = " << endl;
}
String(const char *pstr):_pstr(new char[strlen(pstr) + 1])
{
strcpy(_pstr,pstr);
cout << "String(const char *pstr)" << endl;
}
String(const String & rhs):_pstr(new char[strlen(rhs._pstr) + 1]())
{
strcpy(_pstr,rhs._pstr);
cout << "String(const String &rhs)" << endl;
}
String & operator=(const String & rhs)
{
cout << "String &operator=(const String &rhs)" << endl;
_pstr = rhs._pstr;
return *this;
}
~String()
{
delete [] _pstr;
cout << "~String" << endl;
}
void print();
private:
char * _pstr;
};
void String::print()
{
//cout << "_pstr = " << _pstr << endl;
printf("_pstr = %s\n",_pstr);
}
int main(void)
{
//String str1;//调用默认构造函数
//str1.print();
String str2 = "Hello,world";//调用构造函数String(const char *pstr)
//String str3("wangdao");// 调用构造函数String(const char * pstr)
//str2.print();
//str3.print();
//String str4 = str3; //调用复制构造函数
//str4.print();
//str4 = str2;
//str4.print();
return 0;
}
赋值构造函数
#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
class Computer
{
public:
Computer(const char * brand, double price)
: _brand(new char[strlen(brand) + 1]())
, _price(price)
{
strcpy(_brand, brand);
cout << "Computer(const char *, double)" << endl;
}
Computer(const Computer & rhs)
: _brand(new char[strlen(rhs._brand) + 1]())
, _price(rhs._price)
{
strcpy(_brand, rhs._brand);
cout << "Computer(const Computer&)" << endl;
}
Computer & operator=(const Computer & rhs)
{ //三部曲
cout << "Computer & operator=(const Computer &)" << endl;
if(this != &rhs) {// 自复制
delete [] _brand;//回收左操作数开辟的空间
_brand = new char[strlen(rhs._brand) + 1]();//深拷贝
strcpy(_brand, rhs._brand);
this->_price = rhs._price;
}
return *this;
}
void print()
{
printf(" brand = %p\n", _brand);
cout << " brand:" << _brand << endl
<< " price:" << _price << endl;
}
~Computer()
{
delete [] _brand;
cout << "~Computer()" << endl;
}
private:
char * _brand;
double _price;
};
void test0()
{
Computer pc1("MateBook.....", 6666);
cout << ">> pc1: " << endl;
pc1.print();
//用一个已经存在的对象初始化另一个新对象
Computer pc2 = pc1; //拷贝构造函数(或者说复制构造函数)
cout << ">> pc2: " << endl;
pc2.print();
Computer pc3("Thinkpad", 8888);
cout << ">> pc3: " << endl;
pc3.print();
pc3 = pc1;
//pc3.operator=(pc1);
cout << ">> pc3: " << endl;
pc3.print();
pc2 = pc2;
}
int main(void)
{
test0();
return 0;
}
静态成员函数
#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
class Computer
{
public:
Computer(const char * brand, double price)
: _brand(new char[strlen(brand) + 1]())
, _price(price)
{
strcpy(_brand, brand);
cout << "Computer(const char *, double)" << endl;
_totalPrice += _price;
}
Computer(const Computer & rhs)
: _brand(new char[strlen(rhs._brand) + 1]())
, _price(rhs._price)
{
strcpy(_brand, rhs._brand);
cout << "Computer(const Computer&)" << endl;
}
Computer & operator=(const Computer & rhs)
{ //三部曲
cout << "Computer & operator=(const Computer &)" << endl;
if(this != &rhs) {// 自复制
delete [] _brand;//回收左操作数开辟的空间
_brand = new char[strlen(rhs._brand) + 1]();//深拷贝
strcpy(_brand, rhs._brand);
this->_price = rhs._price;
}
return *this;
}
void print()
{
cout << " brand:" << this->_brand << endl
<< " price:" << this->_price << endl;
}
//静态成员函数没有隐含的this指针
static void printTotalprice()
{//静态成员函数内部不能非静态的成员
//cout << " brand:" << this->_brand << endl
cout << " total price: " << _totalPrice << endl;
}
~Computer()
{
delete [] _brand;
cout << "~Computer()" << endl;
}
private:
char * _brand;
double _price;
//静态成员位于全局静态区, 被整个类所创建的所有对象共享
static double _totalPrice;
};
//全局的位置进行初始化
double Computer::_totalPrice = 0;
void test0()
{
cout << "sizeof(Computer) = " << sizeof(Computer) << endl;
Computer pc1("MateBook.....", 6666);
cout << ">> pc1: " << endl;
pc1.print();
//pc1.printTotalprice();
Computer::printTotalprice();
Computer pc3("Thinkpad", 8888);
cout << ">> pc3: " << endl;
pc3.print();
//pc3.printTotalprice();
Computer::printTotalprice();//静态成员函数可以直接通过类名调用
}
int main(void)
{
test0();
Computer::printTotalprice();
return 0;
}
Empty class
#include <iostream>
using std::cout;
using std::endl;
class Empty
{};
int main(void)
{
Empty e1;
Empty e2;
&e1;
&e2;
cout << "sizeof(e1) = " << sizeof(e1) << endl; // 1
return 0;
}
NullptrCall
#include <iostream>
using std::cout;
using std::endl;
class NullptrCall
{
public:
void func1()
{ cout << "func1()" << endl; }
void func2(int ix)
{ cout << "func2() ix = " << ix << endl; }
static void func3()
{ cout << "func3()" << endl; }
void func4()
{ cout << "func4() _ix " << this->_ix << endl; }
private:
int _ix;
};
int main(void)
{
NullptrCall * p = nullptr;
p->func1();// NullptrCall::func1(nullptr);
p->func2(10);//NullptrCall::func2(nullptr, 10);
p->func3();//NullptrCall::func3();
p->func4();//NullptrCall::fun4(nullptr);
return 0;
}
const的成员函数
#include <iostream>
using std::cout;
using std::endl;
class Point
{
public:
Point()
: _ix(0)
, _iy(0)
{
cout << "Point()" << endl;
}
Point(int ix, int iy)
: _ix(ix)
, _iy(iy)
{
cout << "Point(int,int)" << endl;
}
void setX(int ix)
{ _ix = ix; }
#if 0
void print(/* Point * const this */)
{
//非const版本的成员函数是可以修改成员的
//this = 0x1000;
_ix = 100;
cout << "void print()" << endl;
cout << "(" << this->_ix
<< "," << this->_iy
<< ")" << endl;
}
#endif
//以后只要某一个函数不会对数据成员进行修改,都要将其设置为
//const成员函数
#if 1
void print(/* const Point * const this */) const
{
//_ix = 100;//error
cout << "void print() const" << endl;
cout << "(" << this->_ix
<< "," << this->_iy
<< ")" << endl;
}
#endif
~Point()
{
cout << "~Point()" << endl;
}
private:
int _ix;
int _iy;
};
void func1(const Point & rhs)
{
rhs.print();
}
int main(void)
{
//Point pt1(1, 2);//非const对象调用的是非const成员函数
//cout << "pt1 = ";//非const对象也可以调用const成员函数
//pt1.print();
//const Point pt2(3, 4);//const对象只能调用的const成员函数
//pt2.print();
//func1(pt1);
Point points[5] = {
Point(1, 2),
Point(3, 4)
};
points[0].print();
points[2].print();
return 0;
}
单例设计模式
#include <iostream>
using std::cout;
using std::endl;
//要求: 通过某一个类在内存中只能创建唯一的一个对象
//
//1. 该对象不能是栈(全局)对象
//2. 该对象只能是一个堆对象
//
//单例模式的应用场景有:
//1. 单例模式替换全局变量
//2. 配置文件的内容可以用单例对象存储
//3. 词典文件、网页库
class Singleton
{
public:
static Singleton * getInstance()
{
if(_pInstance == nullptr) {
_pInstance = new Singleton();
}
return _pInstance;
}
static void destroy()
{
if(_pInstance)
delete _pInstance;
}
void print() const
{
cout << "Singleton::data = " << _data << endl;
}
private:
Singleton():_data(0){ cout << "Singleton()" << endl; }
~Singleton(){ cout << "~Singleton()" << endl; }
private:
int _data;
static Singleton * _pInstance;
};
Singleton * Singleton::_pInstance = nullptr;
//Singleton s3;
int main(void)
{
//Singleton s1;//与要求不符合,该语句不能让他编译通过
//s1.print();
//Singleton s2;
//s2.print();
//Singleton * p = new Singleton();
Singleton * p1 = Singleton::getInstance();
Singleton * p2 = Singleton::getInstance();
Singleton::getInstance()->print();
cout << "p1 = " << p1 << endl
<< "p2 = " << p2 << endl;
//delete p1;//该语句不能让他编译通过
//delete p2;//error
Singleton::destroy();
return 0;
}
IO
#include <iostream>
#include <string>
#include <limits>
using std::cout;//std::ostream
using std::cin;
using std::endl;
using std::string;
void printStreamStatus()
{
cout << "cin's badbit = " << cin.bad() << endl
<< "cin's failbit = " << cin.fail() << endl
<< "cin's eofbit = " << cin.eof() << endl
<< "cin's goodbit = " << cin.good() << endl;
}
void test0()
{
int number;
printStreamStatus();
while(cin >> number) {
printStreamStatus();
cout << ">> number = " << number << endl;
}
printStreamStatus();
cout << "clear之后, 流的状态:" << endl;
cin.clear();//重置流的状态
cin.ignore(1024, '\n');//清空缓冲区
printStreamStatus();
string str;
cin >> str;
cout << "str = " << str << endl;
}
void test1()
{
cout << "pls input a interger number:" << endl;
int number;
while(cin >> number, !cin.eof()) {
if(cin.bad()) {
cout << ">> cin stream status is corrupted!" << endl;
return;
} else if(cin.fail()) {
cout << "pls input a valid interger number:" << endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
cout << ">> number = " << number << endl;
}
printStreamStatus();
}
int main(void)
{
//test0();
test1();
return 0;
}
文件IO操作
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::fstream;
using std::ifstream;
using std::ofstream;
using std::string;
using std::vector;
vector<string> file;
void test1()
{
//ifstream要求文件必须存在
//ifstream ifs("test.txt");
ifstream ifs("io2.cc");
if(!ifs.good()) {
cout << "ifstream open file error!" << endl;
return;
}
file.reserve(100);
string line;
//while(ifs >> str) {
while(std::getline(ifs, line)) {
file.push_back(line);
}
//auto 自动推导元素的类型
#if 0
for(auto & line : file)
{
cout << line << endl;
}
#endif
ifs.close();
}
void test2()
{
string filename = "test.txt";
//文件输出流不要求文件存在;
//当文件不存在时,直接创建文件;
//当文件存在时,直接清空文件中的内容
ofstream ofs(filename);
if(!ofs.good()) {
cout << ">> ofstream open error!" << endl;
return ;
}
for(auto & line : file)
{
ofs << line << "\n";
}
ofs.close();
}
void test3()
{
string filename = "test.txt";
//std::ios::app模式可以在文件的末尾追加新的内容
ofstream ofs(filename, std::ios::app);
if(!ofs.good()) {
cout << ">> ofstream open error!" << endl;
return ;
}
cout << "pos: " << ofs.tellp() << endl;
string line = "that's a new line\n";
ofs << line;
ofs.close();
}
void printStreamStatus(fstream & fs)
{
cout << "fs's badbit = " << fs.bad() << endl
<< "fs's failbit = " << fs.fail() << endl
<< "fs's eofbit = " << fs.eof() << endl
<< "fs's goodbit = " << fs.good() << endl << endl;
}
void test4()
{
string filename = "readme.txt";
fstream fs(filename);
if(!fs.good()) {
cout << "fstream open error! " << endl;
return ;
}
int number = -1;
for(size_t idx = 0; idx != 10; ++idx)
{
cin >> number;
fs << number << " ";
}
cout << ">> pos : " << fs.tellg() << endl;
fs.seekg(std::ios::beg);
printStreamStatus(fs);
for(size_t idx = 0; idx != 10; ++idx)
{
fs >> number;
//printStreamStatus(fs);
cout << number << " ";
}
cout << endl;
fs.close();
}
void test5()
{
string filename = "vector.cc";
ifstream ifs;
ifs.open(filename, std::ios::in|std::ios::ate);
if(!ifs.good()) {
cout << ">> ifstream open file error!" << endl;
return;
}
cout << "pos: " << ifs.tellg() << endl;
size_t len = ifs.tellg();
char buff[len + 1] = {0};
ifs.seekg(std::ios::beg);
ifs.read(buff, len);//获取一篇文章的内容
cout << "buff:" << endl << buff << endl;
ifs.close();
}
int main(void)
{
//test1();
//test2();
//test3();
//test4();
test5();
return 0;
}
string IO
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::ifstream;
using std::stringstream;
using std::istringstream;
using std::ostringstream;
void printStreamStatus(stringstream & fs)
{
cout << "fs's badbit = " << fs.bad() << endl
<< "fs's failbit = " << fs.fail() << endl
<< "fs's eofbit = " << fs.eof() << endl
<< "fs's goodbit = " << fs.good() << endl << endl;
}
void test0()
{
int number1 = 1;
int number2 = 2.22;
stringstream ss;
//字符串输出流
ss << "number1= " << number1 << " number2= " << number2;
cout << ss.str() << endl << endl;
//snprintf();
string key;
int value;
while(!ss.eof()) {
ss >> key >> value;
//printStreamStatus(ss);
cout << key << " ---> " << value << endl;
}
}
string int2str(int number)
{
ostringstream oss;
oss << number;
return oss.str();
}
struct Element
{
Element(const string & k, const string & v)
: key(k), value(v)
{}
string key;
string value;
};
void readConfiguration(const string & filename)
{
ifstream ifs(filename);
if(!ifs.good()) {
cout << ">> ifstream open " << filename << " error!" << endl;
return ;
}
vector<Element> config;
string key, value;
string line;
while(getline(ifs, line)) {
istringstream iss(line);
while(!iss.eof()) {
iss >> key >> value;
//cout << key << " --> " << value << endl;
Element element(key, value);
config.push_back(element);
}
}
for(auto & element: config)
{
cout << element.key << " ---> " << element.value << endl;
}
}
void test1()
{
string filename = "my.conf";
readConfiguration(filename);
}
int main(void)
{
//test0();
test1();
return 0;
}
vector
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
void printVectorCapacity(const vector<int> & c)
{
cout << "c's size = " << c.size() << endl;
cout << "c's capacity = " << c.capacity() << endl;
}
int main(void)
{
int arr[10];//静态数组
//动态数组
//策略: 当数组中的size() == capacity(),并且此时还要
//添加新的元素时,需要进行动态扩容。
//
//先去申请2 * capacity() 的空间,然后把原来空间中的
//元素全部复制到新空间中,
//然后去释放原来的空间的数据
//最后再添加新的元素
vector<int> numbers;
numbers.reserve(100);
printVectorCapacity(numbers);
numbers.push_back(1);
printVectorCapacity(numbers);
numbers.push_back(1);
printVectorCapacity(numbers);
numbers.push_back(1);
printVectorCapacity(numbers);
numbers.push_back(1);
printVectorCapacity(numbers);
numbers.push_back(1);
printVectorCapacity(numbers);
numbers.push_back(1);
printVectorCapacity(numbers);
numbers.pop_back();
for(size_t idx = 0; idx != numbers.size(); ++idx)
{
cout << numbers[idx] << " ";
}
cout << endl;
//C++11中的
for(auto & number : numbers)
{
cout << number << " ";
}
cout << endl;
//迭代器访问
auto iter = numbers.begin();
while(iter != numbers.end())
{
cout << *iter << " ";
++iter;
}
cout << endl;
return 0;
}
//要求: 只能生成堆对象,不能生成栈对象
#include <string.h>
#include <stdlib.h>
#include <iostream>
using std::cout;
using std::endl;
//要求: 只能生成堆对象,不能生成栈对象
//解决方案:
// 将析构函数放入private区域, 同时
//还需要定义一个destroy方法, 在destroy方法
//中去执行delete表达式
class Student
{
public:
Student(int id, const char * name)
: _id(id)
, _name(new char[strlen(name) + 1]())
{
strcpy(_name, name);
cout << "Student(int, const char *)" << endl;
}
void print() const
{
cout << "(" << _id << ", " << _name << ")" << endl;
}
//提供一个接口,可以自定义开辟空间的方式
//放在类内部,只针对于Student类型起作用
//放在类之外,对所有的类型都会起作用
static void * operator new(size_t sz)
{
cout << "void * operator new(size_t) " << endl;
return malloc(sz);
}
static void operator delete(void * pointer)
{
cout << "void operator delete(void*)" << endl;
free(pointer);
}
void destroy()
{
//this->~Student();
delete this;
}
private:
~Student()
{
delete [] _name;
cout << "~Student()" << endl;
}
private:
int _id;
char * _name;
};
int main(void)
{
Student * pstu = new Student(100, "Jackie");//ok
pstu->print();
//delete pstu;//error
pstu->destroy();
// Student stu(101, "John");//error
// stu.print();
return 0;
}
//只能生成栈对象, 不能生成堆对象
#include <string.h>
#include <stdlib.h>
#include <iostream>
using std::cout;
using std::endl;
//只能生成栈对象, 不能生成堆对象
//
//解决方案: 将operator new放入private区域
//
class Student
{
public:
Student(int id, const char * name)
: _id(id)
, _name(new char[strlen(name) + 1]())
{
strcpy(_name, name);
cout << "Student(int, const char *)" << endl;
}
void print() const
{
cout << "(" << _id << ", " << _name << ")" << endl;
}
~Student()
{
delete [] _name;
cout << "~Student()" << endl;
}
private:
static void * operator new(size_t sz);
static void operator delete(void * pointer);
private:
int _id;
char * _name;
};
int main(void)
{
Student s1(101, "John");
s1.print();
//Student * pstu = new Student(100, "Jackie");//error
//pstu->print();
//delete pstu;
return 0;
}