我们已经看到c++提供了两种不同的方法来创建数组。
以类似的方式,c++提供了两种不同的方法来创建和使用向量。
最简单的方法是这样的。
std::向量v < int >;int x;While (std::cin >> x) v.push_back(x);(int n = 0; n < v.size (); n + +) std:: cout < < v [n] < < std:: endl;
另一种方法是使用指针访问vector。
std::vector<int> *w; int x; w = new std::vector<int>(); while(std::cin >> x) (*w).push_back(x); for(int n = 0;n < (*w).size();n++) std::cout << (*w)[n] << std::endl; delete w;
在第二个例子中w不是一个向量。相反,w是一个指向向量的指针。向量本身是在语句中创建的
W = new std::vector<int>();
new操作符创建一个新的空int型vector,并返回指向该vector的指针。将该指针赋值给指针变量w,并在代码的其余部分使用w来访问用new创建的向量。
使用指针的一个复杂之处是,每当我们想要访问w所指向的向量时,都必须使用*对指针解引用。这就解释了为什么在上面的例子中会看到类似(*w).size()和(*w)[n]这样的语法。
您在这里看到的最后一个区别是,由于使用new创建了vector,因此在处理完vector后,还必须使用delete释放与vector相关的内存。
在c++中,指针经常用于访问对象。与指针一起工作的一个烦恼是需要不断地解引用指针来处理指针所指向的对象。在上面的例子中,如果我们想问w指向的向量的大小,我们必须说
(* w) .size ();
表达式的*w部分对指针进行解引用,使我们能够访问vector本身。一旦访问了vector对象,就可以调用与该vector对象关联的size()方法。
这种情况在c++编程中经常发生,因此该语言提供了一种更方便的替代语法:
w->size();
您可以使用此语法访问与通过指针到达的对象关联的任何方法。
不幸的是,这种替代语法并不能解决赢博体育问题。我们仍然需要使用解引用来做(*w)[n]。
正如您可以选择如何创建和访问对象一样,您也可以选择如何将对象作为参数传递给函数。
一种选择是按值传递对象。
模板<typename T> void printVector(std::vector<T> v) {for(int n = 0;n < v.size();n++) std::cout << v[n] << endl;}
这个选项使用非常简单和直接的语法。在这个版本中,我们以一种简单直接的方式将向量传递给函数,并在函数内部以一种非常直接的方式使用它。
事实证明,这种方法存在两个问题。第一个问题是,按值传递对象几乎总是会触发复制。在这种情况下,传递给该函数的任何向量都将被复制到形参v中,函数体中的代码将使用该副本而不触及原始版本。如果所讨论的向量非常大,那么这个额外的复制步骤可能会带来不必要的低效率。
第二个问题是,有时当我们将对象传递给函数时,我们确实希望使用原始对象而不是副本。考虑一下这个例子。
模板<typename T> void readVector(std::ifstream in,std::vector<T> v) {T x;While (in >> x) v.push_back(x);}
假设我们尝试在程序中使用这个函数。
std::向量< int >;std:: ifstream;in.open(“numbers.txt”);readVector (,);in.close ();std::cout << “A有” << A.size() << “ items.”< < std:: endl;
运行这段代码将产生以下输出
A有0个元素。
无论文件numbers.txt中有多少个数字。这里发生的情况是,将A按值传递给readVector函数导致生成A的副本,readVector使用该副本而不是原始副本。然后,readVector将继续从文件中读取一堆数据,并将这些数字填充到复制向量中。当退出readVector函数时,复制向量v(连同它的赢博体育数据)将自动消失。原来的向量A在整个过程中都是不变的,并且最终和开始时一样是空的。
考虑到这两个相当严重的问题,我们似乎需要一个替代方案。适当的替代方法是再次使用指针并使用指针形参。
模板<typename T> void readVector(std::ifstream in,std::vector<T> *v) {T x;While (in >> x) v->push_back(x);}
在这个版本中,传递指向vector的指针而不是vector本身。在函数内部,我们使用指针访问vector对象,并将对象放入vector对象中。
可以将这个版本的readVector与以下代码结合使用。
std::向量< int > *;A = new std::vector<int>();std:: ifstream;in.open(“numbers.txt”);readVector (,);in.close ();std::cout << “A有” << A->size() << “ items.”< < std:: endl;删除一个;
在这个版本中,只有一个向量——我们用new创建的向量。将指向该vector的指针传递给readVector函数,readVector使用该指针将数据放入vector中。这样做之后,从readVector调用返回后,vector将报告其中有数据。
您甚至可以对通常不通过指针访问的对象使用指针形参。您可以通过使用“address of”操作符&来获取对象的位置信息:
std::向量< int >;std:: ifstream;in.open(“numbers.txt”);readVector(等);//获取A的地址并传递给readVector in.close();std::cout << “A有” << A.size() << “ items.”< < std:: endl;
将对象作为参数传递给函数还有第三种方法。这种替代方法使用第三种类型的参数,即引用参数。为了表明形参是引用形参,我们在形参后面加上&号。
模板<typename T> void readVector(std::ifstream &in,std::vector<T> &v) {T x;While (in >> x) v.push_back(x);}
引用形参是值形参和指针形参的混合体。引用形参使用普通的按值传递语法,但在幕后,引用形参是通过指针秘密实现的。这意味着引用形参既提供了常规形参的便利性,又具有使用指针的性能优势。
下面有两个例子来演示这个版本的readVector的用法。在这两种情况下,从readVector返回后,所讨论的vector都将报告其中有数据。
//第一个例子std::vector<int> A;std:: ifstream;in.open(“numbers.txt”);readVector (,);in.close ();std::cout << “A有” << A.size() << “ items.”< < std:: endl;//第二个例子std::vector<int> *A;A = new std::vector<int>();std:: ifstream;in.open(“numbers.txt”);readVector (*);in.close ();std::cout << “A有” << A->size() << “ items.”< < std:: endl;删除一个;
注意,在第二个示例中,在将vector传递给readVector函数之前,必须对A指针解引用。