VC.STL Newsgroup Good Questions(四)
Article last modified on 2002-5-30
----------------------------------------------------------------
The information in this article applies to:
- Microsoft Visual C++, 32-bit Editions, version 6.0, SP5
----------------------------------------------------------------
今天提供四个问题。
一.How does STL Map treat pointers?
Question:
STL的Map是如何处理指针的?
比如,我们将一个char*作为key,STL会主动释放它吗?或者这么说,我想确定,当一个item被删除时,我的char*没有被删除。是否Map另外复制了一份char*?
Answer:
是的,Keys和Values都会被复制一份,然后传入(所有的容器都是这样做的)。容器仅仅负责删除这份copy。
所以当你把一个指针放到Map中时,Map不关心这个指针引用的是什么。Map得到并最终删除这个指针的copy。
下面的这个问题可能属于初学者容易犯的错误。不妨看一看吧。
二.Error in Put char* array into queue
Question:
我有这样的代码,是将char*一个一个地放入queue中,然后再将它们弹出来,并打印出来。
void main()
{
typedef queue<char*> CHARQUEUE;
CHARQUEUE q;
char s[10];
for (int i=65;i<81;i++)
{
_strnset(s,i,9);
s[9]='\0';
q.push(s);
}
for (i=61;i<84;i++) {
q.pop();
if(q.size())
cout << q.front()<< endl;
}
}
但是结果不对,为什么?打印出来的各个元素都是”PPPPPPPPP”?
Answer:
原因就是每次循环是都重写了静态分配的字符串数组。你应该使用basic_string,它将为你分配和管理字符串资源,而不是自己手工填充这些Buffers。
修改你的代码如下,也可以(要注意释放malloc出来的东西):
for (int i=65;i<81;i++)
{
char* s = (char*)malloc(10);
_strnset(s,i,9);
s[9]='\0';
q.push(s);
}
剩下的两个问题,都挺简单的,属于HowToDo的问题。第一个:
三.如何用一句话让vector<char*>读写文件?
Question:
我有一个char* vector,如何用一句话将其内容写至一个文件中,或者从文件读至vector,而不是Element By Element地做?
Answer:
假设你想一个vector的元素为文件的一行。那么我们可以这么做:
#include <string>
#include <vector>
#include <iterator>
#include <fstream>
using namespace std;
void main()
{
int VECTOR_SIZE = 10;
vector<char*> vecStrings;
for (int i = 0; i < VECTOR_SIZE; i++)
vecStrings.push_back("Vector Element to File");
ofstream output_file("output_file.txt");
copy(vecStrings.begin(),
vecStrings.end(),
ostream_iterator<char*>(output_file, "\n"));
}
这样,就产生了一个output_file.txt,其内容为:
Vector Element to File
Vector Element to File
。。。
但是,将内容读回来可能有点复杂。Vector<char*>是问题之所在。STL不知道该如何给它分配空间。
如果是vector<string>的话,倒是可以这么做:
copy(istream_iterator<string>(in_file),
istream_iterator<string>(),
back_inserter(vecStrings));
第二个:
四.如何将list中的某个元素上移一位?
Question:
我有一个list,它有10个元素。我想将第6个元素上移至第5位。有什么简单方法可以做的吗?
Answer:
两种方法。
方法一:
使用list::splice。splice的意思就是将当前的元素从源list中去除,然后放到目标list的指定位置。
下面的代码将把list最后一个元素提至最前面,其他元素就会相应后移一位。
#pragma warning(disable : 4786)
#include <iterator>
#include <list>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
void main()
{
list<string> _StringList;
_StringList.push_back(string("Begin! "));
_StringList.push_back(string("AfterBegin "));
_StringList.push_back(string("Body "));
_StringList.push_back(string("BeforeEnd "));
_StringList.push_back(string("End! "));
list<string>::iterator itPoint = _StringList.begin();
for(;itPoint!=_StringList.end();itPoint++)
cout << (*itPoint).c_str() << " ";
list<string>::iterator itSwapIndex = _StringList.begin();
list<string>::iterator itelementBelow = _StringList.end();
itelementBelow--;
_StringList.splice(itSwapIndex, _StringList, itelementBelow);
itPoint = _StringList.begin();
for(;itPoint!=_StringList.end();itPoint++)
cout << (*itPoint).c_str() << " ";
}
方法二:
使用iter_swap function。它将交换iterator所指向的元素。很简单,而且可能更通用一点。
list<string>::iterator itSwapIndex = _StringList.begin();
list<string>::iterator itelementBelow = _StringList.end();
itelementBelow--;
iter_swap(itelementBelow, itSwapIndex);
(To be Continued)
Written by zhengyun@tomosoft.com