Loading

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;
}

 

posted @ 2019-11-03 20:19  RainDavi  阅读(457)  评论(0编辑  收藏  举报