C和C++代码精粹读书笔记

最近看了<<C和C++代码精粹>>, 设计到C++的指针,异常处理等方方面面,其中有些自认为非常不错的代码,在工作中非常值得借鉴。

1.指向成员函数的指针

A

#include<iostream>
using namespace std;
class C
{
    public:
	void f(){ cout<<"C::f\n";}
	void g(){cout<<"C::g\n";}
};

int main()
{
	C c;
	void (C::*pmf)()=&C::f;
	(c.*pmf)();
	pmf=&C::g;
	(c.*pmf)();
}

B

#include<iostream>
using namespace std;

class Object{
public:
    void retrieve(){
        cout<<"Object::retrieve"<<endl;
    }
    void insert(){
        cout<<"Object::insert"<<endl;
    }
    void update(){
        cout<<"Object::update"<<endl;
    }
    void process(int choice);

private:
    typedef void (Object::*Omf)();
    static Omf farray[3];
};

Object::Omf Object::farray[3]={&Object::retrieve,&Object::insert,&Object::update};

void Object::process(int choice){
    if(0<=choice && choice<=2)
        (this->*farray[choice])();
}

int show_menu()
{
    cout<<"1. retrieve\n";
    cout<<"2. insert\n";
    cout<<"3. update\n";
    cout<<"4. quit\n";
    cout<<"Please input a num\n";
    int n;
    cin>>n;
    return n;
}

int main(){
    int show_menu(); 

    Object o;
      for(;;){
        int choice=show_menu();
        if(1<=choice && choice<=3)
            o.process(choice-1);
        else if(choice==4)
            break;
    }
    return 0;
}

2.实现自己的assert宏

//assert.h
#ifndef ASSERT_H
#define ASSERT_H

extern void _assert(char*, char*, long);
#define assert(cond) ((cond) 	? (void) 0 	: _assert(#cond, __FILE__, __LINE__))
#endif

在c文件中定义自己的_assert方法,就可以方便的使用自己的assert宏了:

#include <stdio.h>
#include <stdlib.h>
#include "assert.h"

void _assert(char* cond, char* fname, long lineno)
{
	fprintf(stderr, "Assertion failed: %s, file %s, line %ld\n", cond, fname, lineno);
	abort();
}

int main()
{
	assert(3>4);
	return 0;

}

3.使用setjmp定义超级转向来进行异常处理

#include <stdio.h>
#include <setjmp.h>

jmp_buf jumper;
void exception();
int  deal_exception();

main()
{
     int value = 0;
     int i = 0;

     value = setjmp(jumper);

     if ( 0 == value ) {
         exception();
     }
     else {
         switch ( value )
         {
            case 1:
                printf( "solve exception[%d]\n",value );
                break;
            case 2:
                printf( "solve exception[%d]\n",value );
                break;
            case 3:
                printf( "solve exception[%d]\n",value );
                break;
           default:
                printf( "solve exception[%d]\n",value );
                break;
        }
    }
}

void exception()
{
    int _err_no = 3;

    if ( _err_no == 3 ) {
        printf("exception[%d]\n",_err_no);
        longjmp(jumper,_err_no);
    }

    return;
}

4. 函数模板特化

#include <iostream>
#include <string.h>
#include <string>

using namespace std;

template<class T>
size_t bytes( T& t)
{
	cout<<"(using primary template)\n";
	return sizeof t;
}

size_t bytes( char*& t)
{
	cout<<"(using char* overload)\n";
	return sizeof t;
}

template<>
size_t bytes<wchar_t*>( wchar_t*& t)
{
	cout<<"(using wchar_t* specialization)\n";
	return sizeof 2*(wcslen(t)+1);
}

template<>
size_t bytes<>( string& s)
{
	cout<<"(using string explicit specialization)\n";
	return sizeof s;
}

template<>
size_t bytes<float>( float& s)
{
	cout<<"(using float explicit specialization)\n";
	return sizeof s;
}

int main()
{
	int i;
	cout<<"bytes in i:"<<bytes(i)<<endl;
	const char* s="Hello";
	cout<<"bytes in s:"<<bytes(s)<<endl;
	const wchar_t* w = (wchar_t*)"goodbye";
	cout<<"bytes in w:"<<bytes(w)<<endl;
	string t;
	cout<<"bytes in t:"<<bytes(t)<<endl;

	float f;
	cout<<"bytes in f:"<<bytes(f)<<endl;

	double d;
	cout<<"bytes in d:"<<bytes(d)<<endl;

	return 0;

}

类模板特化

#include <iostream>
using namespace std;

template<class T, class U>
class A
{
public:
	A(){cout<<"Primary template\n";}
};

template<class T, class U>
class A<T*, U>
{
public:
	A(){cout <<"<T*,U> partial specialization\n";}
};

template<class T>
class A<T, T>
{
public:
	A(){cout <<"<T,T> partial specialization\n";}
};

template<class U>
class A<int, U>
{
public:
	A(){cout <<"<int,U> partial specialization\n";}
};

int main()
{
	A<char,int> a1;
	A<char*,int> a2;
	A<float,float> a3;
	A<int, float> a4;

	return 0;
}

5.常量成员函数中改变数据成员的方法

A :this 指针去常量性;B:使用mutable

#include <iostream>
using namespace std;
class B
{
public:
    B() {state =0;pos=0;}
    void f() const;
    void p() {cout<<"state= "<<state<<" pos= "<<pos<<endl;}
private:
    int state;
    mutable int pos;
};
void B::f() const
{
    // ((B*)this)->state=1;
    const_cast<B*>(this)->state=1;
    pos = 1;
}

int main()
{
    B b;
    b.p();
    b.f();
    b.p();

    return 0;
}

6. 信号

#include <stdio.h>
#include <signal.h>
void ctrlc_handler(int sig);

volatile sig_atomic_t ccount = 0;

int main()
{
	char buf[100];
	if(signal(SIGINT, ctrlc_handler) == SIG_ERR)
	{
		fputs("Error installing ctrlc handler\n", stderr);
	}

	while(gets(buf))
	{
		puts(buf);
	}

	signal(SIGINT, SIG_DFL);
	printf("You pressed ctrlc %d times\n", ccount);

	return 0;
}

void ctrlc_handler(int sig)
{
	signal(sig, ctrlc_handler);

	++ccount;
	return;
}

7.异常处理:资源分配即初始化原则

/*
exception:
	logic_error
		domain_error
		invalid_argument
		length_error
		out_of_range
	runtime_error
		range_error
		overflow_error
		underflow_error
	bad_alloc
	bad_cast
	bad_exception
	bad_typeid
*/
#include <cstdio>
#include <memory>
using namespace std;
class File
{
    FILE* f;
public:
    File(const char* fname, const char* mode)
    {
        f = fopen(fname,mode);
        if(!f)
            throw 1;
    }
    ~File()
    {
        if(f)
        {
            fclose(f);
            puts("File closed");
        }
    }
};

int main()
{
    void f(const char*);
    try
    {
        //f("file0.txt");
        f("file1.txt");
    }
    catch(int x)
    {
        printf("Caught exception:%d\n", x);
    }

    return 0;
}

void f(const char* fname)
{
    auto_ptr<File> xp(new File(fname,"r"));
    puts("Processing file...");
    throw 2;
}

8. 非标准模板库容器

#include <valarray>
#include <iostream>
#include <algorithm>
//#include <boost/foreach.hpp>

using namespace std;

void print(double i)
{
    cout << i <<" ";
}
int main()
{
	const int N = 10;
	const double values[N] = {0,1,2,3,4,5,6,7,8,9};
	const valarray<double> v1(values,N);

	//for_each(&values[0], &values[9], ptr_fun(print));
	/*BOOST_FOREACH(double d, values)
	{
		cout<< d << endl;
	} */

	for_each(&v1[0], &v1[10], ptr_fun(print));
	cout<<endl;

	cout << "min: "<<v1.min()<<endl;
	cout << "max: "<<v1.max()<<endl;
	cout << "sum: "<<v1.sum()<<endl;

	return 0;

}

9 处理内存分配异常

A try{} catch(const bad_alloc& x)

B set_new_handler

#include <iostream>
#include <stdlib.h>
using namespace std;

inline void my_handler()
{
	cout << "Memory exhausted" <<endl;
	abort();
}

int main()
{
	set_new_handler(my_handler);

	for(int i=0;;++i)
	{
		(void) new double[100];
		if((i+1) % 10 == 0)
			cout << (i+1) << " allocations" <<endl;
	}

	return 0;
}

10. Never run 9 On your computer!

时间: 2025-02-01 08:57:50

C和C++代码精粹读书笔记的相关文章

简单使用Git和Github来管理自己的代码和读书笔记

以前不知道使用代码管理工具,最后写的一些东西都没有了,由于硬盘坏了或者不小心格式化了之类的,后来使用了Git 和Github来托管自己的代码和读书笔记方便了不少,到哪里只要有网就可以把自己的东西拷贝下来继续使用. 我这里简单的记录一下我使用的过程,最简单的使用都是,高级的功能我一直没有使用到,虽然买一本<Git权威指南> 但是很多东西用不到就不能够真的会.下面开始简单介绍我使用的方法,我这个是在windows上使用的.我使用分两种情况, 因为我的代码都是在Linux下写的,所以在linux下主

JavaScript语言精粹读书笔记- JavaScript对象

JavaScript 对象 除了数字.字符串.布尔值.null.undefined(都不可变)这5种简单类型,其他都是对象. JavaScript中的对象是可变的键控集合(keyed collections). 对象是属性的容器,其中每个属性都拥有名字和值. JavaScript中的对象是无类别的(class-free)的.它对新属性的名字和值没有约束. JavaScript包括一个原型链特性,允许对象继承另一对象的属性. 对象的检索: stooge[“first-name”]或者stooge.

代码大全读书笔记 - 开篇

说起来,<代码大全>这本书书名实在恶俗.在我推荐给展鸿的时候,他说"雾草,这名字看着就像天朝地摊那种XX全书一类的山寨书-" 是的,其实买这个书的原因就是京东买100减30,我买了10块钱的东西,凑了一下单,书到手之前还以为是代码清单,或者以前ACM模板一样的书,甚至买来的一个月里面都拿来当枕头(足足10+cm厚). 这个周末偶然的翻开,才发现,世界上竟然有如此精彩的书,而且很多东西讲的虽然是软件项目,但给了我很多引申到其他东西上面的灵感.很多地方我读到之后,都会兴奋的心跳

《梦断代码》读书笔记 第2篇

<梦断代码>读书笔记 第2篇 第7章:细节视图 第8章:白板上的即时贴 第9章:方法 第10章:工程师和艺术家 第11章:通往狗食版之路 “读书时我喜欢上数学课——这类东西之所以能吸引我,是因为我知道自己做对了.”在书里面我找到了自己刚接触计算机时不喜欢编程可能的原因:我不知道自己是否做对了,也没有很顺利就做对的时候,慢慢地导致排斥编程,特别是一点思路也没有,或者知道这个程序将会花费我很多时间时情绪很糟糕,所以它不能吸引我.到现在,每次找到程序中不对的地方再修改正确,即使消耗很多时间,也会有一

《梦断代码》读书笔记 第0篇

<梦断代码>读书笔记 第0篇 第0章:软件时间 第1章:死定了 第2章:Agenda之魂 从老师布置这个作业之后,我便按照自己的计划开始阅读识字以来的第一本关于软件工程的小说——<梦断代码>,周一至周五每天睡前读几页. 首先,第一遍从第0章至第1章看完,我愣是不知道书上到底在说些什么,感觉这小说跟教科书一样好催眠,说实话,每次还没看多少行就困得不行了.所以,我看了第二遍(而且还寻思着再看不懂也不看第三遍了),果然,我还是没有与作者产生共鸣.不过,在再次阅读的过程中我勾画了一些给自己

C#小常识集锦(一)--《更锋利的CSharp代码》读书笔记

?.采用类似匈牙利命名法为控件命令,对于其他变量申明则不需要了 e.g. Button btnAdd; e.g. TextBox txtUsername; e.g. ListBox lstFileNames; e.g. Panel panelInfo; ?.对于函数参数.局部变量.私有及受保护字段的命名采用Camel规则(首字母小写),其他的情况如命名空间.结构.类.接口.枚举.枚举项.属性.方法.事件.委托及公开的字段等都采用Pascal规则(首字母大写) ?.多使用XML文档注释,它与VS开

《梦断代码之读书笔记之一》

<梦断代码>作者罗森伯格对OSAF 主持的Chandler 项目进行田野调查,跟踪多年,试图借由Chandler 的开发过程揭示软件开发中的一些根本性大问题.本书是讲一事,也是讲百千事:是写一软件,也是写百千软件:是写一群人,也是写百千万人.任何一个在软件领域稍有经验的技术人员看完本书,必掩卷长叹:做软件难.更别说我们还处在软件领域的底层,更是感同身受啊!软件乃是人类自以为最有把握,实则最难掌控的技术. 那是 1975 年的冬天.作者在终端机房中俯身敲击一台电传打字机,每打完一行,那笨重的机头

代码大全读书笔记

在元旦假日看完了这本书,算上目录的话差不多1000页吧,由于这本书主要讲述了思想和流程体系,至于代码结构和优化这一块, 之前有看过设计模式,所以我到也就是过了一遍,所以总体看的很快的并没有精读,至于笔记那也就记了一小部分.基本上并无特别 指出. 但我对这本书的评价还是挺高的,这本书把软件体系的方方面面都进行了总结,通过抛出问题,举出范例然后再加以正确的思路引导. 不过对我而言本书最大的收获并不是了解了软件开发体系,或是高质量的编写代码的方法,而是发现了软件体系中那些边边角角的工作 一些我们常常抱

《梦断代码》读书笔记2

怎样才能使编程像搭积木一样高效而简单呢?考克斯的公司努力了,但是结果让人不是很满意,像乐高积木一样编程是一件幸福的事,但在这样一个悖论:几乎总能找到一段满足大部分需要的代码.但这些拿来的代码所不能做到的部分,恰恰是项目与众不同的创新之处----也是创建这个项目的出发点.打破了我们的美好想法.书中还提到有一种判断程序的标准是判断代码行数,这虽然是一种比较公平的判断标准,但是程序员会因此写出一些可有可无的代码滥竽充数,降低整个软件的执行效率.在我们编写软件的时候,不要把目标定的太高,而是从小项目做起