每天读一点C++Primer!

每天读一点点C++primer!半年读完就可以!

目录
  • 7/4
  • 7/5
  • 7/6
  • 7/7
  • 7/8
  • 7/9
  • 7/10
  • 7/11
  • 7/13

包含了《Effective C++》和《凌波微步》的笔记。。。

7/4

  • 标准库定义了4个l0对象。为了处理输入,我们使用一个名为cin(发音为see-in)的istream类型的对象。这个对象也被称为标准输入(standardinput)。对于输出,我们使用一个名为cout(发音为see-out)的ostream类型的对象。此对象也被称为标准输出(standard output)。标准库还定义了其他两个ostream对象,名为cerr和clog(发音分别为see-err和see-log)。我们通常用cerr来输出警告和错误消息,因此它也被称为标准错误(standard error)。而clog用来输出程序运行时的一般性信息。
  • IO对象无拷贝或者赋值
  • 在函数参数括号写字符串被定义成const char *,最近经常碰到
  • 局部静态对象只在第一次经过时初始化
  • 当形参有顶层const时,传给它常量对象和非常量对象都是可以的
  • 打算明天开始写项目多用指针和引用了,当时学算法不知道听了谁的鬼话尽量不用指针,结果现在还不熟。还是轮子哥说的靠谱。

8.1

#include 
#include 
#include 

using namespace std;
istream& task(istream &a) {

	string m;
	while (a >> m) {
		cout << m << endl;
	}
	a.clear();
	return a;

}
int main()
{
	std::filebuf in;
	if (!in.open("E:/GitCode/Messy_Test/testdata/istream.data", std::ios::in)) {
		std::cout << "fail to open file" << std::endl;
		return;
	}
	istream wss(&in);

	task(wss);

}

istream是所有输入类型的基类,直接cin调用即可。
6.2.1

#include "stdio.h"

void change(int* a, int* b) {
	int c = *a;
	*a = *b;
	*b = c;
}
int main() {
	int a, b;
	a = 1;
	b = 2;
	int* c = &a;
	int* d = &b;
	change(c, d);
	printf("a=%d b=%d",a,b);
}

6.2.2

#include "stdio.h"

void change(int& a, int& b) {
	int c = a;
	a = b;
	b = c;
}
int main() {
	int a, b;
	a = 1;
	b = 2;
	change(a, b);
	printf("a=%d b=%d", a, b);
}

6.2.3

#include "stdio.h"
#include 

std::string::size_type find_char(std::string& const s,char c,std::string::size_type &occurs) {
	auto ret = s.size();
	occurs = 0;
	for (decltype(ret)i = 0; i != s.size(); i++) {
		if (s[i] == c) {
			if (ret == s.size()) {
				ret = i;
			}
			++occurs;
		}
	}
	return ret;
}
int main() {
	std::string s = "sdafodsago";
	std::string::size_type ctr;
	auto index = find_char(s, 'o', ctr);
	
}

问题:我不明白一个课后问题,为什么std::string::size_type find_char(std::string& const s,char c,std::string::size_type &occurs)这个函数三个参数必须分别是现在的格式?或者说第一个参数用引用比不用引用好在哪里?(必须被定义为const的前提下)
明天打算重读引用那一章找出答案。

7/5

  • 昨天问题的答案是:引用避免了新建对象,提高了速度
  • 引用本身不是对象,不能定义引用的引用
  • 如果你想要一个string形参能够接受常量,那么使用const;事实上,任何无需在函数中改变的字符串都应该被定义为常量引用
int *matrix[10];		//十个指针构成的数组
int (*matrix)[10];		//指向含有十个整数的数组的指针
  • const cast用于改变const属性
  • 一旦函数的某个形参被赋予了默认值,它后面的参数必须都有默认值
  • 内敛函数可以在调用点内联展开,适用于优化流程直接规模小调用频繁的函数。
  • constexpr函数是指能用于常量表达式的函数,它被隐式地指定为内联函数
  • constexpr函数是指能用于常量表达式的函数:函数的返回值类型和所有形参的类型必须是“字面值类型”:算术、引用、指针。并且函数体内有且只有一条return语句。

6.2.4

#include "stdio.h"
#include
#include
using namespace std;
int function(int a,int *b,int *c) {
	std::cout<< *c++;
	std::cout << *c++;
	return 0;
}
void error_msg(initializer_list il) {
	for (auto beg = il.begin(); beg != il.end(); beg++) {
		cout << *beg;
	}
}
void add(initializer_list il) {
	int sum = 0;
	for (auto beg = il.begin(); beg != il.end(); beg++) {
		sum += *beg;
	}
	cout << sum;
}
int main(int argc, char **argv) {
	int a = 1,b = 2;
	int *c = &b;
	int j[2] = { 0,1 };
	//function(a, c,j);
	argv[0];
	//std::cout << argv[1] << argv[2];
	
}

6.3.2


#include "stdio.h"
#include
#include
using namespace std;

char &get_val(string &str, string::size_type ix) {
	return str[ix];
}

int main() {
	string s("a value");
	cout << s << endl;
	get_val(s, 0) = 'A';
	cout << s << endl;
	return 0;
}

#include "stdio.h"
#include
#include
#include
#include 
using namespace std;

char &get_val(string &str,string::size_type ix) {
	return str[ix];
}
int mainx() {
	return 100000;
}
vector process() {
	return { "i","am","sb" };

}
int  (*func(int i))[10]{
	return 0;
}
//尾置返回类型
auto funcc(int i)->int(*)[10]{

}

//decltype
int odd[] = { 1,3,5,7,9 };
decltype(odd) *arrPtr(int i) {

}
string *testO(string &a) {

}

const string &shorterString(const string & s1, const string &s2) {
	return s1.size() <= s2.size() ? s1 : s2;
}
string &shorterString(string &s1, string& s2) {
	
}




int main() {
	string a[] = {"a","b","c"};
	testO(&a[]);

	string s("a value");
	cout << s << endl;
	get_val(s, 0) = 'A';
	cout << s << endl;
	return EXIT_FAILURE;


	return EXIT_SUCCESS;
}

7/6

  • assert(expr)预处理宏,如果表达式为0,输出信息并且终止程序执行;如果为真,则什么也不做。
  • 预处理名字由预处理器而非编译器管理,因此不需要using声明。
  • 宏名字必须在程序内唯一,含有cassert头文件的程序不能再定义名为assert的变量。
  • 预处理器定义的五个程序调试很有用的名字(iostream)

__func__存放函数名
__FILE__存放文件名的字符串字面量
__LINE__存放当前行号的整型字面量
__TIME__存放文件编译时间的字符串字面量
__DATE__存放文件编译日期的字符串字面量

  • char在函数类型转换是对于int和short会匹配int

  • const类型转换:判别方式是判断实参是否是常量来决定选择哪个函数。指针类型的形参判别也是类似的。

  • 类型提升:不是完全相同,皆会提升类型,char会提升为int。

  • 算术类型转换:该转换的级别都相同,即3.14是double,转换成long或者float都是同样等级,会产生二义性。

  • ·typedef int(*p)(int a, int b); 声明函数指针,未初始化,p为指向函数的指针。使用typedef的声明语句定义的不再是变量而是类型别名就是将变量转化为类型别名的一种方式,p原来是指向函数的指针变量,现在变成了指向函数的指针变量的类型别名.

#include 
#include 
void print(const int ia[], size_t size) {
#ifndef NDEBUG
	//__func__存放函数名
	//__FILE__存放文件名的字符串字面量
	//__LINE__存放当前行号的整型字面量
	//__TIME__存放文件编译时间的字符串字面量
	//__DATE__存放文件编译日期的字符串字面量
	std::cerr << __func__ << ":array size is " << size << std::endl;
#endif // !1

}
int calc(int&, int&);
int calc( int& const,  int& const);

bool(*pf)(const std::string &, const std::string &);

//pf=lengthCompare;
//pf=&lengthCompare;


void main() {
	const int ia[3] = { 1,2,3 };
	print(ia, 3);
}

7/7

考试,,其实是玩了一天dota2(悲)

7/8

  • 在类的成员函数后面加const被称为常量成员函数,实质上是把函数隐式的this指针改变成了常量。常量对象以及常量对象的引用或指针都只能调用常量成员函数。
  • 编译器首先编译成员的声明,其次编译成员函数体。因此成员函数体可以无视成员出现顺序调用。
  • 使用=default来要求编译器生成构造函数
  • 构造函数不能轻易覆盖类内初值,除非与原址不同,如果不能使用类内初始值,那么所有构造函数都应该显式地初始化每个内置成员
  • struct和class定义类唯一的区别就是默认的访问权限。如果使用struct关键字,定义在第一个访问说明符之前的是public的,class则是private的。
  • 知识点1:友元—类允许其他类或者函数访问其非共有成员,只要在本类内,加一条类前或者函数前有friend关键字(最前方)的声明即可。最好在类的开始或结尾集中声明友元。
    优点:可以灵活地实现需要访问若干类的私有或受保护成员才能完成的任务,便于与其他不支持类的语言进行混合编程;通过使用友元函数重载可以更自然第使用C++语言的I/O流库。
    缺点:一个类将对非公有成员的访问权授予其他的函数或类,会破坏该类的封装性,降低该类的可靠性和可维护性。
  • 名字查找的顺序:由内而外、自上而下
  • 类的定义处理步骤:首先编译成员的声明,直到类全部可见是再编译函数体
    即成员函数在类的声明全部处理完之后才会被定义,所以可以调用函数中定义的任何名字
  • 在类中,类型名要特殊处理,最好是定义在类的一开始,并且不能与外层作用域中同名
  • Type有两种类型,应将最后一个函数的Type也声明为Exercise::作用域,因为返回值是double类型
#include 
#include 
struct Sales_data {
	std::string bookNo;
	std::string units_sold;
	std::string revenue;
	std::string isbn() const { return bookNo; }
	//const作用是修改隐式this指针的类型
	//std::string Sales_data::isbn(const Sales_data *const this) {
	//	return this->isbn;
	//}
	Sales_data& combine(const Sales_data &rhs);
};


Sales_data& Sales_data::combine(const Sales_data &rhs) {
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, const Sales_data&);


std::istream &read(std::istream& is, const Sales_data& item){
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;

}

Sales_data total(cin);
	if (cin)
	{
		Sales_data trans(cin);
		do
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(cout, total) << endl;
				total = trans;
			}
		}while (read(cin, trans));
		print(cout, total)<

7/9

做了一天OS课设,没看。。。

7/10

做了一天机械设计课设,还是没看。。。

7/11

  • 编译器只会自动执行一步类型转换
  • 使用explicit修饰构造函数可以阻止构造函数的隐式类型转换,并且只能用于直接初始化
  • 对重载函数声明友元函数,需要对这组函数的每一个分别声明。

7/13

  • 在类中不能重定义外层作用域中的名字,和一般情况相反。
  • 必须通过构造函数初始值列表为const、引用的成员赋值
  • 成员初始化顺序和它们在类定义中出现的顺序一致
  • 一个良好的用户自定义类型的特征是它们避免无端的与内置类型不兼容。

你可能感兴趣的:(每天读一点C++Primer!)