C++ 基础
1. mutable
#include <iostream>
using namespace std;
class MyClass {
mutable int i;
int j;
public:
int geti() const {
return i; // ok
}
void seti(int x) const {
i = x; // ok
}
/* 下面这个函数则编译不通过
void setj(int x) const {
j = x; // 错
}
*/
};
int main()
{
MyClass ob;
ob.seti(1900);
cout << ob.geti();
return 0;
}
2. 变长参数
cstdarg
#include <cstdarg>
#include <iostream>
using namespace std;
template <typename T>
T summary(int count, ...) {
T total = 0;
va_list list;
va_start(list, count);
for (int i = 0; i < count; ++i) {
total = total + va_arg(list, T);
}
va_end(list);
return total;
}
int main(int argc, char *argv[])
{
// 注意,这儿输入的参数必须是double, 也就是必须要是1.0 而不是1
double result = summary<double>(4, 1.0, 2.0, 3.0, 4.5);
cout << result << endl;
return 0;
}
3. time
ctime
std::time_t time( std::time_t* arg);
time函数 返回当前时间,并将其转码为time_t对象,然后将之存在参入传入的对象中,除非arg是一个空指针。
也可以写作 time_t time = time(NULL);
错误时,返回(std::time_t)(-1)
std::tm* localtime( const std::time_t *time );
localtime函数 将传入的time转换为本地时间。
std::tm* gmtime(const std::time_t* time);
gmtime函数 将传入的time转换为UTC时间。
char* asctime(const std::tm* time_ptr);
asctime函数 将传入的时间转换为格式为 Www Mmm dd hh:mm:ss yyyy\n 的字符串
e.g. 1462102142 -> Sun May 1 19:26:59 2016
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
time_t currentTime;
time(¤tTime);
cout << currentTime << endl;
cout << localtime(¤tTime) << endl;
cout << asctime(gmtime(¤tTime)) << endl;
return 0;
}
4. C++11新特性
4.1 lambda
[函数对象参数] (操作符重载函数参数)->返回值类型{ 函数体 }
- [a] 值传递
- [&a] 引用传递
- [=] 所有外部变量
- 默认const, 可以加mutable
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vi{1, 2, 3, 4, 5};
for_each(vi.begin(), vi.end(), [](int v) { cout << v << endl;});
int a = 5; int b = 6;
for_each(vi.begin(), vi.end(), [a](int v) { cout << v+a << endl;});
for_each(vi.begin(), vi.end(), [=](int v) { cout << (double)(v+a)/b << endl;});
return 0;
}
4.2 auto & decltype
auto实际上实在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响。
另外,似乎auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹 配。
auto a; // 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定a的类型
auto i = 1;
auto d = 1.0;
auto str = "Hello World";
auto ch = 'A';
auto func = less<int>();
vector<int> iv;
auto ite = iv.begin();
auto p = new foo() // 对自定义类型进行类型推导
在模板中的应用,
// 当我们没有auto时 我们可能需要这样写
template <typename Product, typename Creator>
void processProduct(const Creator& creator) {
Product* val = creator.makeObject();
...
}
// with auto
template <typename Creator>
void processProduct(const Creator& creator) {
auto val = creator.makeObject();
...
}
decltype: 实际上有点像auto的反函数,auto可以让你声明一个变量,而decltype则可以从一个 变量或表达式中得到类型,
int x = 3;
decltype(x) y = x;
4.3 nullptr
nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型.
#include <cstdlib>
#include <cassert>
#include <iostream>
using namespace std;
void F(int a) {
cout<<a<<endl;
}
void F(int *p) {
assert(p != NULL);
cout << p << endl;
}
int main(){
int *p = nullptr;
int *q = NULL;
bool equal = ( p == q ); // equal的值为true,说明p和q都是空指针
int a = nullptr; // 编译失败,nullptr不能转型为int
cout << equal << endl;
F(0); // 在C++98中编译失败,有 义性;在C++11中调 F(int) F(nullptr);
return 0;
}
4.4 序列for循环
可用于数组 容器 和 string
map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};
for (auto p : m){
cout << p.first << " : " << p.second << endl;
}
5. 利用tuple返回变长数据
/**
* tuple: 一种可以存放多个不同种类元素的多元组
* 例如: auto t = make_tuple(1, 2.0, "C++ 11", {1, 0, 2});
* make_tuple(): 创建tuple对象
* tie(): 创建一个tuple,其中的值是参数的引用
* get(): 从tuple提取元素
**/
#include <tuple>
#include <iostream>
#include <string>
#include <stdexcept>
std::tuple<double, char, std::string> get_student(int id)
{
if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");
if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
throw std::invalid_argument("id");
}
int main()
{
auto student0 = get_student(0);
std::cout << "ID: 0, "
<< "GPA: " << std::get<0>(student0) << ", "
<< "grade: " << std::get<1>(student0) << ", "
<< "name: " << std::get<2>(student0) << '\n';
double gpa1;
char grade1;
std::string name1;
std::tie(gpa1, grade1, name1) = get_student(1);
std::cout << "ID: 1, "
<< "GPA: " << gpa1 << ", "
<< "grade: " << grade1 << ", "
<< "name: " << name1 << '\n';
}
输出
ID: 0, GPA: 3.8, grade: A, name: Lisa Simpson
ID: 1, GPA: 2.9, grade: C, name: Milhouse Van Houten