C++ Data Structure 学习笔记 (2011.5.3)——传值,指针,引用的区别及Vector与String的详细用法

时间:2021-03-13 16:37:49

今天学的第一个内容是传值,传引用的问题。在Mark Weiss的书中,他非常简明扼要的对此作了说明:

Call by reference is required for objects that may be altered by the function.

 

Call by value is appropriate for small objects that should not be altered by the function.

 

Call by constant reference is appropriate for large objects that should not be altered by the function.

在日常的编程中,Call by value应该说最为常见,但是这个仅限于传递一些容量很小的object,并且这个传递的值在函数中不应该被改变。

 

然而,对于Vector以及String这样的large object来说,肯定不能用传值来进行,还用昨天的例子。

void getInts( vector<int> & array )

{

    int inputVal;

 

    array.resize( 0 );

    cout << "Enter any number of integers: ";

    while( cin >> inputVal )

        array.push_back( inputVal );

}

 

#endif

 

// Test getInts.

int main( )

{

    vector<int> array;

 

getInts( array );

cout<<array.size()<<endl;

    for( int i = 0; i < array.size( ); i++ )

        cout << array[ i ] << endl;

 

    return 0;

}

 

这就是个典型的传引用,我们希望array里面的东西在函数中被改变,所以用这种向量数组的引用方式来传递。比如我现在随便输三个数 221232324,调用函数后,vector的长度是3,因为储存了三个数,初始的长度0被修改。如果我们不想改变数组的长度,在前面加const就好,但是这个时候,任何企图修改数组的行为都将被认为是错误,比如array.resize( 0 );重置他的大小,或者pushback往里面加元素之类的。

再来个更经典的例子来说明传值,传引用,传指针的区别

// Does not work

void swapWrong( int a, int b )

{

    int tmp = a;

    a = b;

    b = tmp;

}

 

// C Style -- using pointers

void swapPtr( int *a, int *b )

{

    int tmp = *a;

    *a = *b;

    *b = tmp;

}

 

// C++ Style -- using references

void swapRef( int & a, int & b )

{

    int tmp = a;

    a = b;

    b = tmp;

}

 

// Simple program to test various swap routines

int main( )

{

    int x = 5;

    int y = 7;

 

    swapWrong( x, y );

    cout << "x=" << x << " y=" << y << endl;

    swapPtr( &x, &y );

    cout << "x=" << x << " y=" << y << endl;

    swapRef( x, y );

    cout << "x=" << x << " y=" << y << endl;

 

    return 0;

}

在函数SwapRef的调用过程中,是不需要&号的,because an address is implicitly passed by virtue of the fact that the corresponding formal parameters are references. The code involving the use of reference parameters is much more readable。个人也同样很喜欢传引用的方式,毕竟是C++的方法啊。

 

 

接下来,继续学习关于String类的有关知识。C语言中是没有String这个类型的,只有string.h文件,包含了一些处理字符串处理的函数,可以用charC中定义字符串的内容。C++中,String属于first class object,因此可以*的用 =”,“==,”+=”这些符号对字符串进行复制,比较等操作。

string a = "hello";

string b = "world";

string c;

c += b;

当然,还可以用cout输出字符串的内容。

cout << "c is: " << c << endl;

Vector类相同,String类也可以通过” . ”操作来用一些类中build-in的函数,比如获取长度,字符串反转操作等等。特别要说的是,可以通过.c_str()这个方法把字符串对象中的内容,c语言字符串的方式输出. 回传字符串指针,这种指针主要是用来传给某些传统的c语言函数比如文件操作等等。

char*   ptr   =   str.c_str();

 

初始化string类型的方法很简单,可以直接申明string类的对象并赋值

string a = "hello";

也可以申明string类的指针,指向一段内容

string *strPtr = new string( "hello" ) ;

 

 

这里顺便提一下箭头(->)操作符和点(.)操作符的区别

c++中当定义类对象是指针对象时候,就需要用到-> 指向类中的成员,其实也可以用点,但是麻烦,编程的估计都怕麻烦吧;当定义一般对象时候时就需要用到 ". "指向类中的成员。

比如我如果直接定义Vector类型的成员

vector<int>a(3);

那么添加一个元素的方式就是

a.push_back(22);

如果申明的是指向向量的指针

vector<int>*b = new vector<int>;

当然你可以这么写(*b) .push back(33),但是又是星号又是括号的,为了简便,干脆定义了一种专门针对指针调用函数的写法b->push_back(33);

 

 

Ok,然后来说一说访问向量元素的几种方法。一种是直接访问,比如:

cout <<a[0]<<endl

但是这种方式访问极不安全,如果越界神马的就会有红色的错误框框出现。

C++ Data Structure 学习笔记 (2011.5.3)——传值,指针,引用的区别及Vector与String的详细用法 

安全的做法是采用Vector类中的at函数来进行,如果越界,程序将停止往下执行。

 

最后说个自己当年用Vector时候的错误,蛮典型的还是。

 

a.push_back(22);

cout <<a.at(0)<< endl;

输出的结果是几呢?

你会不会说结果是22呢?答案是0.错误的原因在于没有理解pushback的工作原理,它的原理是Adds a new element at the end of the vector。因此如果之前分配了3个单位空间,22出现的位置是2位置的再后面一位3位置而非0位置。如果想达到0位置我22的目的改起来也很简单,去掉vector<int>a(3);后面的(3)即可,这样就是动态的分配空间啦。