您的位置:首页 > 编程语言 > C语言/C++

菜鸟学C++

2004-11-23 10:30 531 查看
2004/7/2
------------------------------------------------------------------------------------------
how to debug register?here is a example:

typedef struct regs_t
{
DWORD eax;
DWORD ebx;
DWORD ecx;
DWORD edx;
DWORD esp;
DWORD ebp;
DWORD esi;
DWORD edi;
} REGS;

#define SHOW_REGS(x) REGS __regs;/
__asm {mov __regs.eax, eax}/
__asm {mov __regs.ebx, ebx}/
__asm {mov __regs.ecx, ecx}/
__asm {mov __regs.edx, edx}/
__asm {mov __regs.esp, esp}/
__asm {mov __regs.ebp, ebp}/
__asm {mov __regs.esi, esi}/
__asm {mov __regs.edi, edi}/
char __regs_text[128];/

2004/8/20
------------------------------------------------------------------------------------------
int* p,q;
第一眼看去,好像是p和q都是int*类型的,但事实上,只有p是一个指针,而q是一个最简单的int型变量。
int (*p)[4]=RollNum;
int *q[5];

这里,p被声明为一个指向一个4元素(int类型)数组的指针,而q被声明为一个包含5个元素(int类型的指针)的数组。

另外,我们还可以在同一个声明中混合实用*和&,如下:

int **p1; // p1 is a pointer to a pointer to an int.
int *&p2; // p2 is a reference to a pointer to an int.
int &*p3; // ERROR: Pointer to a reference is illegal.
int &&p4; // ERROR: Reference to a reference is illegal.

注:p1是一个int类型的指针的指针;p2是一个int类型的指针的引用;p3是一个int类型引用的指针(不合法!);p4是一个int类型引用的引用(不合法!)。
const int *p;
int const *q;

他们当中哪一个代表const int类型的指针(const直接修饰int),哪一个代表int类型的const指针(const直接修饰指针)?实际上,p和q都被声明为const int类型的指针。

2004/9/1
------------------------------------------------------------------------------------------
1 for_each和表达式模板(expression template)??????10么dd
2 纯虚拟私有函数?

2004/9/2
------------------------------------------------------------------------------------------
微软风格就是if(0==i)这种,因为可以防止出现写成if(i=0)这样if后的语句肯定被执行的情况

2004/9/2
------------------------------------------------------------------------------------------
from csdn
假设
int a[10]
p1=a;

那么
*p++=1;
*++p=2;
++*p=3;
(*p)++=4;

分别应该怎么按照优先级别运算?
按照书上的说法++ (后置) >++(前置) >* 解引用用 > = 等于
*p++ 是否应该是 现算(p++) 在算* 最后 赋值?
求所有的正确的算法 和解答
---------------------------------------------------------------

++(后缀)属于“后缀操作符”,其优先级高于“前缀操作符”。
* 和++(前缀)都属于“前缀操作符”,优先级相同,按从左到右结合的顺序。都高于赋值运算符。

所以:
*p++=1 相当于 (*(p++)) = 1,也就是说++操作于p上,结果为p原来的值,再作*运算,去除引用,再赋为1。总的作用就是把p引用的对象赋值为1,并把p加1。

*++p=2 相当于(*(++p)) = 2,也就是说++操作于p上,结果为p加1后的值,再作*运算,去除引用,再赋值为1。总的作用就是把p加1,然后对其引用的对象赋值为2。

++*p=3 相当于(++(*p)) = 3,也就是说先对p作*运算去除引用,其结果为p引用的对象,再把这个对象+1,结果还是这个对象,再把它赋值为3。这个表达式要求对象的前缀++操作符的返回值为左值。

(*p)++=4 这里有一个强制优等级(括号),它的级别最高,结果就是((*p)++) = 4,也就是先对p作*运算去除引用,其结果为它引用的对象,然后对这个对象作后缀++操作符,结果为这个对象操作前的值(一般是一个临时变量),然后把它赋值为4,这个表达式要求对象的后缀++操作符的返回值为左值(整数类型是不符合要求的,只对定义了这个操作符的对象类型才有可能符合要求)。

这个问题以C中很难试验出来,在C++中可以用操作符重载的方法看清楚(操作符重载不会改变优先级):

#include <iostream>

class test
{
public:
test(){}
test(int){}
test& operator = (const test&){std::cout<<"Assignment of test" << std::endl; return *this;}
test& operator ++ (){std::cout << "Prefix ++ of test" << std:: endl; return * this;}
test& operator ++ (int) {std::cout << "Suffix ++ of test" << std::endl; return *this;}
};
class testptr
{
test Value;
public:
testptr& operator = (const test&){std::cout<<"Assignment of testptr" << std::endl; return *this;}
testptr& operator ++ (){std::cout << "Prefix ++ of testptr" << std:: endl; return * this;}
testptr& operator ++ (int) {std::cout << "Suffix ++ of testptr" << std::endl; return *this;}
test& operator *(){std::cout<< "Operator * of testptr"<<std::endl; return Value;}
};

#define TRACK(X) std::cout <<std::endl<<"***** "<< #X << " *****" <<std::endl; X
int main()
{
testptr p;
TRACK(*p++=1);
TRACK(*++p=2);
TRACK(++*p=3);
TRACK((*p)++=4);
std::cin.get();
}

输出为
***** *p++=1 *****
Suffix ++ of testptr
Operator * of testptr
Assignment of test

***** *++p=2 *****
Prefix ++ of testptr
Operator * of testptr
Assignment of test

***** ++*p=3 *****
Operator * of testptr
Prefix ++ of test
Assignment of test

***** (*p)++=4 *****
Operator * of testptr
Suffix ++ of test
Assignment of test

int p = 1;
int a = p++;
结果a=1,并不是因为后缀++优先级低(我记得有一本C教材就是这样写的,真是误人子弟),而是由后缀++的语义决定的。标准的后缀++应该是“对操作对象做+1操作,并返回操作前的值”,它在赋值运算前运算了,但它的返回值并不是p,而是p在做+1运算前的值。因此我们还可以知道,p++的返回值应该不是一个左值,p++=a是无法编译通过的。而前缀++则不一样,++p的含义就是“对p做+1运算,并返回p”,其返回值就是p本身(引用),是一个左值,++p = a是可以编译的(但没什么意义)。

如果用代码描述一下这两个操作符,应该是这样的:

const int int::operator ++(int)//后缀++
{
int temp = *this;
*this = *this +1;
return temp;
}

int& int::operator ++()//前缀++
{
*this = *this + 1;
return *this;
}

补充:
在C中,上述语句含义分别是:
*p++=1; --> temp = p + 1; *temp = 1;
*++p=2; --> p = p +1; * p = 1;
++*p=3; --> *p = *p + 1; *p = 3;
(*p)++=4;//语法错误,无法写出对应的语句。

由于后缀增/减量操作符的特殊性,导致初学者很难理解“为什么后缀的++优先级高却后对变量加1呢?”事实上,事实上,“后缀++”并不是后对变量加1,而是先做了,只是它的返回值并不是这个变量,而是这个变量改变前的值。如果对它很难理解,建议不要使用这几个操作符,而改用普通的加/减法操作符:
*p++=1; --> *p = 1; p = p + 1;
*++p=2; --> p = p + 1; *p = 2;
++*p=3; --> *p = *p + 1; *p = 3;
(*p)++=4;//语法错误,无法写出对应的语句。

由于在C++中这几个操作符不再是整数和指针类型特有的,而是可以为类定义的,并且它们可以和+/-1操作语义不同或根本没有加/减法操作符(如双向迭代器),不能简单地用加/减法代替。不过C++程序员们可以通过看比较好的类的操作符重载函数(如迭代器的)代码真正明白后缀增/减量操作符的语义,不会因为它“优先级高却后对变量加1”的问题糊涂。不过,仅管如此,我还是认为使用增/减量操作符时最好让一个表达式中或者没有增/减量操作符,或者只有一个增/减量操作符,如:++p;*p = 1;(相当于*++p = 1)或*p = 1;++p;(相当于*p++=1),这样也不用去区分前缀和后缀的区别了。

2004/9/2
------------------------------------------------------------------------------------------
我已经包含了objbase.h并调用了CoInitialize(0),
报错如下:
'CoCreateInstanceEx' : undeclared identifier

---------------------------------------------------------------

do you have defined _WIN32_DCOM or defined _WIN32_DCOM larger than or equal 0x400?
---------------------------------------------------------------

stdfax.h加上这个
#define _WIN32_WINNT 0x0500

afxDump是一个CDumpContext类型的全局变量

2004/11/20
------------------------------------------------------------------------------------------
结构编译对齐方式
VC c1 /Zp1 (or Porject->Settings->C/C++->Code Generation->Struct menber alignment)
BCB bcc32 -a1

2004/11/21
------------------------------------------------------------------------------------------
1 try
{
throw("dsfsdfsdf");
}
catch(float x)
{
printf("Hello World!/n");
}
catch(char* x)
{
printf("Hello World!/n");//执行这句
}
2 try
{
throw("dsfsdfsdf");
}
catch(float x)
{
printf("Hello World!/n");//执行这句
}
3 try
{
throw(1);
}
catch(float x)
{
printf("Hello World!/n");
}
catch(int x)
{
printf("Hello World!/n");//执行这句
}
4 try
{
throw(1);
}
catch(float x)
{
printf("Hello World!/n");//执行这句
}
看来C中catch各子句并不像CPP中对象一样。
5 try
{
throw(1);
}
catch(...)
{
printf("Hello World!/n");
}
catch(int x)
{
printf("Hello World!/n");
}
编译出错!catch(...)必须在最后

2004/11/23
------------------------------------------------------------------------------------------
《凌波微步》
打开速度优化开关的指令:
VC c1 /O2
Linux g++ -O2

优化后的指令
1 将for循环的实现改成了do while结构
2 更多的利用系统寄存器
3 优化开关必一定久必不用快!参见P140,系统函数strlen()的实现(VC98/CRT/SRC/Intel/STRLEN.ASM)。每次比较4字节vs每次比较1字节

2006/1/12
------------------------------------------------------------------------------------------
虚拟继承的测试:
class Point { public: int x;};
class Point3d : public Point {};
class Vertex : virtual public Point {};
class Vertex3d : public Point3d, public Vertex {};
class pVertex : public Vertex3d {};

int main ()
{
Vertex3d v;
v.Point3d::x = 1;
v.Vertex::x = 2;
printf("%d %d/n",v.Point3d::x, v.Vertex::x);
getchar();
return 0;
}

输出 1 2
如果是class Point3d : virtual public Point {};输出2 2

1/18/2006

------------------------------------------------------------------------------------------

It's one of the classic basic forms for malloc arguments:

1 object_ptr = malloc(N * sizeof *object_ptr);
2 string_ptr = malloc(STRING_LENGTH + 1);
3 void_ptr = malloc(sizeof variable);

Notes: 1 the parenthesis is not necessory for sizeof; 2 the * position

------------------------------------------------------------------------------------------

1/26/2006

foo * and const foo * are different types but are nevertheless similar
enough that you can use const_cast to cast between them. Where two types are
used as template arguments, however, the similarity of the types is
irrevant. Consider:

template<class T>
class Test
{
T t;

};

template<>
class Test<const int>
{
char array[1000];

};

Thus Test<const int> contains an array of chars, whereas Test<int> contains
a single int.

#include <iostream>
using namespace std;

int main()
{
Test<int> t1;
Test<const int> t2;
cout << sizeof(t1) << endl; // gives 4
cout << sizeof(t2) << endl; // gives 1000
return 0;

}

In reality vector<foo *> and vector<const foo *> may hardly differ at
all --- in particular, they may have the same size. However, the possibility
of explicit template specialization means that they could differ
spectacularly, hence the reluctance of the compiler to allow conversion.

------------------------------------------------------------------------------------------
1/27/2006

You should not pass temporary objects by reference unless the reference
is a const. Because by the time the code gets to look at the non const
temporary object that was referenced, the temporary object may or may
not exists.

2/9/2006 about stream
------------------------------------------------------------------------------------------

There's an idiom (and a supporting member function) for checking
the state of a stream, which allows a stream object to be used
in a boolean context. But converting it to a boolean value
doesn't 'just happen'. To do so requires the use of a boolean
logical operator (a stream's 'value' itself is not boolean).
(The member function is 'operator void*', you can research it
if you like).

Try this

if(!outFile)
// stream in is error state
else
// stream is in 'good' state

If you want the first test to be for 'good' state, you
can write:

if(!!outFile)

or:

if(outFile.good())

BTW if you only need output, you should use 'std::ofstream'.
'std::fstream' is intended for streams which are both read
from and written to.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: