常见的C++知识

编程基础文章目录:

五大基础算法 基础数据结构(栈和队列) 散列表
常见C++知识 基础数据结构(数组、串、广义表) 四大比较排序算法
基础数据结构(线性表) 基础数据结构(树和堆)  

微博:LinJM-机器视觉 Blogger:LinJM

这一篇其实是流水账,主要记录我查阅过的C++知识。

static const size_type npos = -1;

This is a special value equal to the maximum value representable by the type size_type. The exact meaning depends on context, but it is generally used either as end of string indicator by the functions that expect a string index or as the error indicator by the functions that return a string index.

查找字符串a是否包含子串b,


不是用strA.find(strB) > 0而是strA.find(strB) != string:npos


string::size_type pos = strA.find(strB);
if(pos != string::npos){}


memset 

用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为' '或'\0'。

void * memset ( void * ptr, int value, size_t num );
Fill block of memory
Sets the first  num bytes of the block of memory pointed by  ptr to the specified  value (interpreted as an  unsigned char).

Parameters

ptr
Pointer to the block of memory to fill.
value
Value to be set. The value is passed as an  int, but the function fills the block of memory using the  unsigned char conversion of this  value.
num
Number of bytes to be set to the  value.
size_t is an unsigned integral type.
memset主要应用是初始化某个内存空间。
memcpy
是用于copy源空间的数据到目的空间中。
strcpy
用于字符串copy,遇到‘\0’,将结束。


fputs函数和fflush函数

fputs

int fputs ( const char * str, FILE * stream );
Write string to stream
Writes the  C string pointed by  str to the  stream.

fflush

int fflush ( FILE * stream );
Flush stream
If the given  stream was open for writing (or if it was open for updating and the last i/o operation was an output operation) any unwritten data in its output buffer is written to the file.


关于*&连用的意思

template <class S, class T> static inline void clone(T*& dst, S* src, int n)
{
	dst = new T[n];
	memcpy((void *)dst,(void *)src,sizeof(T)*n);
}
上面clone函数里有T*& dst这个参数。下面看知乎上的一段回答:

常见的C++知识_第1张图片

memcpy函数

void * memcpy ( void * destination, const void * source, size_t num );
Copy block of memory Copies the values of num bytes from the location pointed by source directly to the memory block pointed by destination.       The underlying type of the objects pointed by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.    The function does not check for any terminating null character in source - it always copies exactly num bytes.
To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least numbytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).
/* memcpy example */
#include <stdio.h>
#include <string.h>

struct {
  char name[40];
  int age;
} person, person_copy;

int main ()
{
  char myname[] = "Pierre de Fermat";

  /* using memcpy to copy string: */
  memcpy ( person.name, myname, strlen(myname)+1 );
  person.age = 46;

  /* using memcpy to copy structure: */
  memcpy ( &person_copy, &person, sizeof(person) );

  printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );

  return 0;
}

inline

在c++中,为了解决一些频繁调用的小函数大量消耗栈空间或者是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数。 如svm.cpp中的一段代码:

#ifndef min
template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }//static函数只能在本文件中使用
#endif
#ifndef max
template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
#endif

静态变量和动态变量

extem、register、static、auto分别是定义外部变量、寄存器变量、静态变量、自动变量,其中,自动变量和寄存器变量属于动态存储,调用时临时分配单元;而静态变量和外部变量属于静态存储,在整个程序运行时都存在。 

scanf函数

定义在<stdio.h>中,是格式转换函数,即按用户指定的格式从键盘上把数据输入到指定的变量中。

成功输入则返回“1”。

头文件必须使用保护宏

C++中防止头文件被包含两次有两种方法解决:

【A:保护宏】

#ifndef _ABCDE_H 
#define _ABCDE_H 
//代码部分
#endif
在被包含过一次之后,宏_ABCDE_H已经有了,下次再碰到就会略过从#define _ABCDE_H开始到#endif之间的代码

【B:还有一种特定编译器支持的指令:】

b.#pragma once 

能保证该文件(物理上的)只被编译一次,也能起到防止重复包含的作用

但这2种方式是有区别的:

a.Macro guard可移植性好,绝大多数编译器都支持,而且万一不小心拷贝了几分相同的代码也不会出问题,但你得确保这个宏名不会与其他的宏冲突,否则等编译器报出一大堆错误的时候你可能会觉得莫名其妙;

b.#pragma once指令简单,它能保证该文件(物理上的)只被编译一次,不用去费劲的想不同的宏名,但如果有几份该文件的拷贝,显然起不到作用。

Release版称为发行版,Debug为调试版

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。 

更多细节:VC++中Debug调试版本和Release发行版本的区别

static的作用

static关键字可以用于声明变量、函数、类数据成员、类函数。
By default, an object or variable that is defined outside all blocks has static duration and external linkage. Static duration means that the object or variable is allocated when the program starts and is deallocated when the program ends. External linkage means that the name of the variable is visible from outside the file in which the variable is declared. Conversely, internal linkage means that the name is not visible outside the file in which the variable is declared.
The static keyword can be used in the following situations.

  1. When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.
  2. When you declare a variable in a function, the static keyword specifies that the variable retains its state between calls to that function.
  3. When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. A static data member must be defined at file scope. An integral data member that you declare as const static can have an initializer.
  4. When you declare a member function in a class declaration, the static keyword specifies that the function is shared by all instances of the class. A static member function cannot access an instance member because the function does not have an implicit this pointer. To access an instance member, declare the function with a parameter that is an instance pointer or reference.
  5. You cannot declare the members of a union as static. However, a globally declared anonymous union must be explicitly declared static.
在标准C++中引入命名空间之前,程序中必须将名字声明为static,使它局部于一个文件。文件中静态声明的使用从C语言继承而来,在C语言中,声明为static的局部实体在声明它的文件之外不可见。不过现在C++不赞成文件静态声明。不赞成的特征是在未来版本中可能不支持的特征。应该避免文件静态而使用未命名空间代替。《C++ Primer 4th》pp605

一个变量如果位于函数的作用域内,但生命周期却跨越了这个函数的多次调用,则将这样的对象定义为static(静态的)。static局部对象确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化。这种对象一旦被创建,在程序结束前都不会被撤销。当定义静态局部对象的函数结束时,静态局部对象不会撤销。在该函数的多次调用的过程中,静态局部对象会持续存在并保持它的值。《C++ Primer 4th》pp220

size_t count_calls()
{
	static size_t ctr = 0; //value will persist across calls
	return ++ctr;
}
int main()
{
	for (size_t i = 0; i != 10; ++i)
		cout << count_calls() << endl;
	return 0;
}

stringstream介绍

C++中引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件。

  1. istringstream类用于执行C++风格的串输入操作
  2. ostringstream类用于执行C++风格的串输出操作
  3. stringstream类用于执行C++风格的串输入/输出操作

stringstream通常用于做数据转换。

istringstream类是从istream和stringstreambase派生而来,ostringstream是从ostream和 stringstreambase派生而来, stringstream则是从iostream类和stringstreambase派生而来。它们的继承关系如下:

#include <string>
#include <sstream>
#include <iostream>
int main()
{
	std::stringstream stream;
	std::string result;
	int i = 10000;
	stream << i; //将int输入流
	stream >> result; //从stream中抽取前面插入的int值
	std::cout<<result <<std::endl;//print the string “10000”
}
更多细节:C++ stringstream介绍,使用方法与例子

explicit关键字

explicit关键字只能用于类内部的构造函数声明上。

我们可以将构造函数声明为explicit,来防止在需要隐式转换的上下文使用构造函数(当构造函数被声明为explicit时,编译器将不使用它作为转换操作符)


更多细节:Explicit 关键字

const全解析

1、定义const对象

const限定符提供了一个解决办法,它把一个对象转换成一个常量。

const int bufSize = 512;

现在任何修改bufSize的尝试都会导致编译错误。因为常量在定义后就不能修改,所以定义时必须初始化。

const std::string hi = "hello!"; //OK

const int i, j = 0;                     //error,i没有初始化

2、const对象默认为文件的局部变量

非const变量默认为extern。要使const变量能够在其他文件中访问,必须显示指定它为extern。

3、const引用

const引用是指向const对象的引用。

const int ival = 1024;

const int &refVal = ival; // OK

int &ref2 = ival;             // error , 可以读取但不能修改

4、指向const对象的指针

若指针指向const对象,则不允许使用指针来改变其所指的const值。

为了保证这个特性,C++强制要求指向const对象的指针也必须具有const特性。

const double * cptr;

这里的cptr是一个指向double类型const对象的指针,const限定了cptr指针所指向的对象类型,而并非cptr本身,即cptr本身并不是const。在定义时不需要对它进行初始化,若需要允许给cptr重新赋值,使其指向另一个const对象,但不能通过cptr修改其所指对象的值。

在实际程序中,指向const的指针常用作函数的形参,将形参定义为指向const的指针以此确保传递给函数的实际对象在函数中不因为形参而被修改。

5、const指针

const指针本身的值不能被修改。

int errNumb = 0;

int *const curErr = &errNumb;

const指针的值不能修改,这意味着不能使curErr指向其他对象。任何企图给const指针赋值的行为都会导致编译错误。

6、指针和typedef

在typedef中使用指针往往会带来意外的结果。下面是一个几乎所有人刚开始都会答错的问题。假定给出以下语句:

typedef string* pstring;

const pstring cstr; // const string * cstr;

请问cstr是什么类型?

很多人会认为是const string * cstr。也就是说,const pstring是一种指针,指向string类型的const对象,但是这是错误的。错误的原因在于将typedef看作文本扩展。

声明const pstring时,const修饰的是pstring的类型,这是一个指针。因此,该声明语句是把cstr定义为指向string类型对象的const指针,这个定义等价于:

string *const cstr:

extern

C++程序通常由许多文件组成。为了让多个文件访问相同的变量,C++区分了声明和定义。

变量的定义(definition)用于为变量分配存储空间,还可以为变量指定初始值。在一个程序中,变量有且只有一个定义。

声明(declaration)用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字。可以通过extern关键字声明变量名而不是定义它。不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern:

extern int i; // declares but does not define i

int i;            // declares and defines i

extern声明不是定义,也不分配存储空间。事实上,它只是说明变量定义在程序的其他地方。程序中变量可以声明很多次,但是只能定义一次。

static const char * stageTypes[] = {CC_BOOST};

  • 静态全局变量 static int n;

静态全局变量在声明它的整个文件都可见,而在文件之外是不可见的(这样其他文件可以定义相同名字的变量,不冲突)

  • 静态数据成员

在类内数据成员的声明前加上关键字static。

静态数据成员被当作类的成员,无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝。由该类型的所有对象共享访问。

静态数据成员 初始化:

<数据类型><类名>::<静态数据成员名> = <值>

在类外进行初始化。

C++中的参数传递

  • 传值:这是默认的参数传递方式

使用传值方式,把实参的值传给函数局部工作区相应的副本中,函数使用这个副本执行必要的功能。这样,函数修改的是副本的值,实参的值不变

  • 引用类型

使用引用传递参数,需要将形参声明为引用,当一个实参与一个引用形参结合时,传递的是实参地址。节省传递参数时间和副本空间。

动态存储分配 new 和delete

Point *p = new Point[100];

delete [] p;

virtual int getSize() const = 0;

这个是纯虚函数,纯虚函数是一个在基类中说明的虚函数,它在该基类中没有具体定义,但要求在它的派生类中定义自己的版本,或者重新说明为纯虚函数。
而后面跟的那个const是说明成员函数getSize()是常量成员函数,const成员函数不能修改调用该函数的的对象,即getSize()只能读取而不能修改它们对象的数据成员。


参考文献:

[1] C++ 头文件[.h]中保护宏的用法 [EB/OL]. [2013-12-23].http://blog.sina.com.cn/s/blog_656c58ac0101fhoz.html

[2] VC++中Debug调试版本和Release发行版本的区别[EB/OL].[2013-12-23]. http://blog.csdn.net/yeyang911/article/details/12951611

[3] MSDN STATIC(C++)http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx

[4] Lippman S B, Lajoie J, Moo B E, et al. C++ PRIMER 中文版: 特别版[M]. 人民邮电出版社, 2010.


你可能感兴趣的:(scanf,static,stringstream,explicit关键字)