函数

#include<iostream>
using namespace std;



//局部 静态对象
size_t count_calls() {
	static size_t ctr = 0;
	return ++ctr;
}

//使用引用避免拷贝
bool isShorter(const string& s1, const string& s2) {
	return s1.size() < s2.size();
}

//使用标记指定数组的长度
void print(const char* cp) {
	if (cp) //cp不是一个空指针
		while (*cp) //指针所指的字符不是空字符
			cout << *cp++;
}

//数组引用形参,c++允许将变量定义为数组的引用,基于同样的道理,形参也可以是数组的引用
void print(int(&arr)[10]) {
	for (auto elem : arr) {
		cout << elem << endl;
	}

//注意:f(int &arr[10]) 将arr声明为引用的数组   f(int (&arr)[10]) arr是具有10个整数的整形数组的引用

}

//传递多维数组
void print(int(*matrix)[10], int rowsize) { //matrix代表指向含有10个整数的数组指针
	return;
}
//等价于
void print(int matrix[][10], int rowsize) { //matrix代表指向含有10个整数的数组指针
	return;
}

//含有可变形参的函数
void error_msg(initializer_list<string> il) {
	for (auto beg = il.begin(); beg != il.end(); ++beg) {
		cout << *beg << " ";
	}
	cout << endl;
}
string expected = "abc";
string actual = "def";
void test2() {

if (expected != actual) {
	error_msg({ "functionx", expected, actual });
}
else {
	error_msg({ "functionx", "okay" });
}

}


//省率符形参
//void foo(parm_list, ...);
//void foo(...);


//不要返回局部对象的引用或指针
const string& manip() {
	string ret;
	if (!ret.empty())
		return ret; //错误,返回局部对象的引用
	else
		return "empty"; //错误,empty是一个局部临时量
}

//返回数组指针
typedef int arr[10];
using arr = int[10];
arr* func(int i); //func返回一个指向含有10个整数的数组的指针
/*
int (*func(int i))[10];
func(int i):代表调用func时需要一个int类型的实参
(*func(int i)):我们可以对函数调用的结果执行解引用操作
(*func(int i))[10]:解引用func的调用将得到一个大小是10的数组
int (*func(int i))[10] :表示数组中的元素是int类型

*/


//使用尾置返回类型
auto func(int i) ->int(*)[10];
//func接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组

//使用decltype
int odd[] = { 1, 3, 4, 7, 9 };
int even[] = { 0, 2, 4 ,6, 8 };
decltype(odd)* arrptr(int i) {
	return (i % 2) ? &odd : &even;
}


//const_cast和重载
const string& shoererString(const string& s1, const string& s2) {
	return s1.size() <= s2.size() ? s1 : s2;
}
//这个函数的参数和返回类型都是const string的引用,我们可以对两个非常量的string实参调用这个函数,但是返回的结果任然是const string的引用
//因此我们需要引进一个新的shorterString函数,当他的实参不是常量时,得到的结果是一个普通的引用,使用const_cast可以做到
string &shorterString(string& s1, string& s2) {
	auto &r = shorterString(const_cast<const string&>(s1), const_cast<const string&>(s2));
	return const_cast<string&>(r);
}//报错了,不知道为什么


//重载与作用域
string read();
void print(const string&);
void print(double);
void fooBar(int ival) {
	bool read = false; //新的作用域,隐藏了外层的read
	//string = read(); //错误,read是一个布尔值,而非函数
	void print(int);
	//print("value"); //print(const string&)被隐藏了
	print(3.14);
}

//内联函数和constexpr函数
inline const string& shorterString(const string& s1, const string& s2) {
	return s1.size() <= s2.size() ? s1:s2;
}
//constexpr函数的返回类型及所有形参的类型必须都是字面值类型,而且函数体中必须有且只有一条 rerun语句
constexpr int new_sz(){
	return 42;
};
constexpr int foo = new_sz();

//返回指向函数的指针
using F = int(int*, int); //F为函数类型,不是指针
using PF = int(*)(int*, int); //PF为指针类型
PF f1(int); //PF是指向函数的指针,F1返回指向函数的指针
int (*f1(int))(int*, int); 
//f1有形参列表,所以f1是一个函数,f1前面有*,所以f1返回一个指针,指针类型本身也包含形参列表,因此指针指向函数,该函数的返回值为int
auto f1(int) -> int(*)(int*, int);



void test() {
	void f1() ; //隐士的定义空参数列表
	void f2(void); //显示的定义空参数列表

	//自动对象:存在于块执行期间的对象称为自动对象,当块的执行结束后,块中创建的自动对象的值就变成未定义的

	//const形参与实参
	const int ci = 42;
	int i = ci;
	int* const p = &i;
	*p = 0;

	//下列三种形式是等价的
	void print(const int*);
	void print(const int[]);
	void print(const int[10]);

}

int main() {
	system("pause");
	return 0;
}
posted @ 2022-03-09 17:30  W-forever  阅读(36)  评论(0)    收藏  举报