21天学会C++笔记

#include


#是预处理标志,每次启动编译器时,先运行预处理器。
include是一条预处理指令,意思是:“后面跟的是一个文件名,请找到此文件并从这里将它读入”

int main()


向操作系统返回一个值相对来说是一个并不重要并且甚少使用的功能,但C++标准要求必须像上面那样声明main()函数。

某些编译器会要求你声明main()返回void,这已不再是合法的C++,请不要养成这种坏习惯。让main()返回int,只需返回0即可。设定返回值为0,表示程序正常结束。

#include<iostream>

int main() {
std::cout << "Hello,World";
std::cout << std::endl;
return 0;
}


使用std::是非常烦人的一件事情。尽管使用namespace指定是一种很好的方式,但是大量的输入时很讨厌的。ANSI标准可以有两种方法来解决这个小问题。

第一种方法,在代码清单开始的位置告诉编译器你将使用标准库函数count和endl

#include<iostream>

int main() {
using std::cout;
using std::endl;

cout << "Hello,World";
cout << endl;
return 0;
}


第二种方法是告诉编译器我们将要使用全部的namespace标准,这就是说,没有特殊指定的任何对象可以假定都来自于标准namespace。在这种情况下,我们用using namespace std来代替using std::cout

#include<iostream>

int main() {
using namespace std;

cout << "Hello,World";
cout << endl;
return 0;
}


在C++中,变量是存储信息的地方。变量是内存中的一个地址,在这个地址中可以进行数据的存储和读取。

C++区分大小写

所谓匈牙利命名法是指变量名中包含可反映变量类型的字符前缀。例如,整型变量都以小写"i”为为首字母。其他如常量、全局变量、指针等等都是如此。这种做法在C编程中更显重要。发明人是匈牙利人Charles Simonyi。

C++允许你一次创建多个类型相同的变量。

对于unsigned short int,如果在程序中多出使用,那么要一次次输入它们就是一件既繁琐又极易出错的事情。C++允许你用关键字typedef(表示类型定义)为这个短语创建一个别名。

typedef unsigned short int USHORT;


在C++中有两种定义符号常量的方法。
[list]
[*]传统的旧方法而现在已被废弃的方法是利用预处理器指令#define。
[*]尽管#define已能满足需要,但在C++中有一种新的,更好的定义常量的方法:用const定义常量。
如:const unsigned short int studentPerClass = 15;
[/list]

枚举型常量可用整型常量替代。

全局函数存在于对象之外,成员函数(也称成员方法)存在于对象之内。

所有函数都有返回值,如果未明确返回值类型,则系统自动默认为整型。

函数体内声明的变量称为局部变量,因为这种类型只局部地存在该函数本身。当函数返回时,局部变量不再有效;它们被编译器标记以用于析构函数。

传递给函数的参数也可被视为局部变量。

在程序块中定义的变量只在该程序块的范围内有效;它们只能在这个块内被访问,当块结束时,这些变量就不存在了。全局变量有全局访问范围,可在程序内的任何地方使用。

在任一函数外部定义的变量称为全局变量,这种变量对程序中的任何函数均有效,包括main()函数。

在C++中,全局变量时合法的,但人们几乎从不使用它们。C++提供了一种强大全局变量的替代者:静态成员变量。

允许在函数的任何地方定义变量,而不限定只在函数开头定义变量。

传递到函数内的变元对该函数来说是局部的。对这些变元的所有改动都不影响调用函数中的值,这称为用值传递,也就是说在函数中生成每个变元的一个局部拷贝。

对于函数原型:
long myFunction(int Param1, int Param2, int Param3)
只有当Param3使用默认值时,你才能让Param2使用默认值;只有Param2,Param3均使用默认值,你才能让Param1使用默认值。

在跳入或跳出函数的过程中存在着一些影响性能的系统开销。(所以用inline)

当函数调用它本身时,系统会在内存中为该函数再创建一个新备份。而这个新备份中的局部变量也独立于前一个备份中的局部变量,这与前面讲过的被调用函数中的局部变量与main()中的局部变量相互独立式一样的。

在C++中,结构体与类相似,只是结构体的成员默认为公有成员。

类的对象在内存中的大小由类的成员变量的大小的总和来决定,类方法不占用为该对象所分配的那部分内存。

C++程序员所使用的最有力的工具之一就是指针,通过它可以直接对内存进行操作。

指针是保存内存地址的变量。

值为0的指针我们称之为空指针,所有的指针在定义时都应该初始化。如果你不知道自己想给指针赋什么值,那就赋为0。没有初始化的指针我们称之为失控指针(wild pointer)。失控指针是非常危险的。一定要对指针初始化。

所有指针都是四个字节。

指针提供了对变量值的间接访问,指针保存该变量的地址。通过以下语句,你可以使用指针pAge把howOld的值赋给新变量:

unsigned short int yourAge;
yourAge = *pAge;

间接引用运算符(*)的含义是:“存储在此地址处的值”。这条赋值语句的含义是:“把存储在pAge中的地址处的值赋给yourAge”。

指针有以下三种用途:
1. 处理自由存储区的数据
2. 访问类的成员数据和函数
3. 通过引用的方式向函数传递变量

局部变量和函数形参位于栈中,当然代码位于代码区,全局变量位于全局变量区。寄存器则用于内部管理,例如保存栈顶指针和指令指针等。所有剩余的内存空间都被作为自由存储区,有时也被称为堆。

在C++中使用关键字new分配自由存储区中的内存。

new的返回值是内存的地址

当你不再需要一块内存空间时,必须对指向它的指针使用关键字delete。它的作用是释放内存,把它交还给自由存储区。一定要记住:与所指向的内存区域不同,指针本身是个局部变量。当声明指针的函数返回时,指针的作用域也就结束了,因此被丢弃了。然而,使用关键字new分配的内存不会被自动释放,于是这块内存不能由其他数据使用。这种情况我们称之为内存泄露。这种情况被称为内存泄露时因为直到程序结束内存才能恢复使用,就好像计算机“丢掉”了这块内存一样。

#include <iostream>

int main()
{
using std::cout;

int localVariable = 5;
int * pLocal = &localVariable;
int * pHeap = new int;

*pHeap = 7;

cout << "localVariable: " << localVariable << "\n";
cout << "*pLocal: " << *pLocal << "\n";
cout << "*pHeap: " << *pHeap << "\n";

delete pHeap;

*pHeap = 9;

cout << "*pHeap: " << *pHeap << "\n";
delete pHeap;

return 0;
}


虽然22行看起来似乎是多余的(程序结束时会释放所占用的内存),但显示的释放是较好的想法。如果程序需要改变或者要进行扩展,采取这一步将是有益的。

另一种可能造成内存泄露的情况是:在没有删除一个指针之前就对其重新赋值。考虑一下代码


unsigned short int * pPointer = new unsigned short int;
*pPointer = 72;
pPointer = new unsigned short int;
*pPointer = 84;


删除指向自由存储区中的对象的指针时,在内存释放之前会调用对象的析构函数。这使你可以像在栈中一样删除对象。

要访问成员函数GetAge,可以使用以下语句:
(*pRags).GetAge();
使用括号是为了保证在访问GetAge()之前对pRags进行间接引用。
因为这样会比较麻烦,C++为间接访问对象的成员提供了一个简单的运算符:成员指针运算符“->”。它由一个横杠“-”和一个大于号“>”组成,在C++中把它们作为一个符号处理。

每个类的成员函数都有一个隐藏的参数:this指针。This指针指向每一个单独的对象。因此,每一次调用GetAge()函数或SetAge()函数,指向特定对象的this指针都作为隐含的参数。

当你删除指针时,实际是让编译器释放内存,但是指针本身依然存在。它现在即使一个迷途指针。

在指针的类型之前或之后可以使用关键字const,也可在这两个位置同时使用。例如,以下都是合法的声明:


const int * pOne;
int * const pTwo;
const int * const pThree;


pOne是一个指向整型常量的指针。该指针指向的值是不能改变的。
pTwo也是一个指向整型的指针,它指向的整数可以改变,但是pTwo这个指针不能指向其他变量。
pThree是一个指向整型常量的指针,它指向的值不能改变,并且这个指针也不能指向其他变量。

如果你声明了一个指向const型对象的指针,通过该指针你只能调用const方法。

strncpy
  char * strncpy(char *s1,char *s2,size_t n);
  将字符串s2中最多n个字符复制到字符数组s1中,返回指向s1的指针。
  注意:如果源串长度大于n,则strncpy不复制最后的'\0'结束符,所以是不安全的,复制完后需要手动添加字符串的结束符才行。
  Strcpy和Strncpy的区别
  第一种情况:
  char* p="how are you ?";
  char name[20]="ABCDEFGHIJKLMNOPQRS";
  strcpy(name,p); //name改变为"how are you ? "====>正确!
  strncpy(name,p,sizeof(name)); //name改变为"how are you ? " ====>正确!
  第二种情况:
  char* p="how are you ?";
  char name[10];
  strcpy(name,p); //目标串长度小于源串,错误!
  name[sizeof(name)-1]='\0'; //和上一步组合,弥补结果,但是这种做法并不可取,因为上一步出错处理方式并不确定
  strncpy(name,p,sizeof(name)); //源串长度大于指定拷贝的长度sizeof(name),注意在这种情况下不会自动在目标串后面加'\0'
  name[sizeof(name)-1]='\0'; //和上一步组合,弥补结果
  ================================================
  总结:strcpy
  源字串全部拷贝到目标字串中,包括'\0',但是程序员必须保证目标串长度足够,且不与源串重叠。
  strncpy
  如果目标长>=指定长>源长,则将源串全部拷贝到目标串,连同'\0'
  如果指定长<源长,则将截取源串中按指定长度拷贝到目标字符串,不包括'\0'
  如果指定长>目标长,错误!

函数:isalnum
  头文件:ctype.h
  功能:如果本函数的变元为字母或数字,它将返回非零值,否则返回零值。

  示例:
  #include <ctype.h>
  #include <stdio.h>
  int main(void)
  {
  char ch;
  int total;
  total=0;
  do
  {
  ch=getchar();
  if(isalnum(ch))
  total++;
  }while(ch!='.');
  printf("The total of the alphanumerics is %d",total);
  return 0;
  }
  运行结果:
  输入:1234567890io我. 回车
  输出结果:13

引用就是一个别名;当声明一个引用时,应该把它初始化为另一个对象名,也就是目标。从这时起,引用就成为目标的替代名,所有对引用的操作实际都是对目标的操作。

函数有两个限制:
1) 使用值传递参数
2) 返回语句只能返回一个值

使用引用把值传递给函数可以打破这两个限制。

#include <iostream>

int main()
{
char string[10] = {'A','l','a','b','a','m','a','\0'};

for(int i=0; i<10; i++)
{
if(!string[i])
std::cout << i << "false";
}

return 0;
}


7false8false9false


#include <iostream>

int main()
{
//char string[10] = {'A','l','a','b','a','m','a','\0'};
char string[15] = "how are you";

for(int i=0; i<15; i++)
{
std::cout << (int)strlen(string) << std::endl;
if(!string[i])
std::cout << i << std::endl << "false";
}

return 0;
}


11
11
11
11
11
11
11
11
11
11
11
11
11
false11
12
false11
13
false11
14
falsePress any key to continue . . .

说明只要不是'\0',其它输出的都是true,包括空格输出地也是true。

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

bool GetWord(char * theString, char * word, int& wordOffset);

int main()
{
const int bufferSize = 255;
char buffer[bufferSize+1];
char word[bufferSize+1];
int wordOffset = 0;

std::cout << "Enter a string: ";
std::cin.getline(buffer, bufferSize);

while(GetWord(buffer, word, wordOffset))
{
std::cout << "Got this word: " << word << std::endl;
}

return 0;
}

bool GetWord(char * theString, char * word, int& wordOffset)
{
//只要不是'\0'都会输出true,可以用来判断是否已经到了结尾
if(!theString[wordOffset])
return false;

char *p1, *p2;
p1 = p2 = theString+wordOffset;

//很显然,这条语句的作用是在一开始跳过非字母的符号。
//p1指向当前单词的第一个字母(假如有单词的话),或者指向字符串的末尾
//(非字母)
for(int i=0; i<(int)strlen(p1) && !isalnum(p1[0]); i++)
p1++;

//假如没有字母了,就返回错误
if(!isalnum(p1[0]))
return false;

p2 = p1;
while(isalnum(p2[0]))
p2++;

int len = int(p2 - p1);

strncpy(word, p1,len);

word[len]='\0';

for(int j=int(p2-theString); j<(int)strlen(theString) && !isalnum(p2[0]);j++)
{
p2++;
}

wordOffset = int(p2-theString);

return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值