C++ C++;将一个向量附加到另一个向量
我完全理解这个问题被问了很多次,但我要求的是一个具体的变体,我的搜索foo已经放弃了,因为我只找到了将一个现有向量附加到另一个向量的算法,而没有找到从函数返回的算法 我有一个列出目录中所有文件的函数:C++ C++;将一个向量附加到另一个向量,c++,stl,vector,append,C++,Stl,Vector,Append,我完全理解这个问题被问了很多次,但我要求的是一个具体的变体,我的搜索foo已经放弃了,因为我只找到了将一个现有向量附加到另一个向量的算法,而没有找到从函数返回的算法 我有一个列出目录中所有文件的函数: vector<string> scanDir( const string& dir ) vector scanDir(常量字符串和目录) 它可以在内部调用自己(对于子目录) 我需要一种将返回值附加到调用方向量的简单方法。我脑子里有这样的想法(但它当然不存在:(): 矢量文件
vector<string> scanDir( const string& dir )
vector scanDir(常量字符串和目录)
它可以在内部调用自己(对于子目录)
我需要一种将返回值附加到调用方向量的简单方法。我脑子里有这样的想法(但它当然不存在:():
矢量文件列表;
//...
append(scanDir(subdirname));
我担心存储返回值并将其插入文件列表会导致性能下降。我的意思是:
vector<string> temp( scanDir(subdirname) );
copy( temp.begin(), temp.end(), back_inserter(fileList) );
vector temp(scanDir(subdirname));
复制(临时开始(),临时结束(),返回插入器(文件列表));
谢谢
PS:我不会强迫自己使用vector,任何其他性能同样好并可以防止潜在的大拷贝操作的容器对我来说都是好的。而不是
vector<string> temp( scanDir(subdirname) );
为什么不将向量作为参数传递呢?这样,每次调用都可以附加到同一个向量,而无需复制。或者创建一个将元素累积到成员对象中的实现类。递归函数必须将所有内容复制多次,精确地说是O(深度)(即:叶级中的所有内容都将被一次又一次地复制,直到到达根) 最好的方法是将其拆分为两个不同的函数:
vector<string> scanDir(string path)
{
vector<string> retval;
scanDir(path, &retval);
return retval;
}
static void scanDir(string path, vector<string>& output)
{
.. scan
.. append to output
}
vector scanDir(字符串路径)
{
向量检索;
scanDir(路径和返回);
返回返回;
}
静态空扫描(字符串路径、向量和输出)
{
扫描
…附加到输出
}
PS:我并没有强迫自己使用vector,任何其他性能同样好并可以防止潜在的大拷贝操作的容器对我来说都是好的
好的,如果你使用
列表并调用a.splice(a.end(),b);
你将完全避免复制操作。列表通常是一个链表,而不是像向量那样的数组,因此这对性能和使用有很大影响。但是splice在O(1)中运行,这是一个很好的好处。辅助函数怎么样
template<class T>
std::vector<T>& VectorAppend(std::vector<T> &target, const std::vector<T> &source)
{
size_t insertPos = target.size();
target.resize(target.size() + source.size());
std::copy(source.begin(), source.end(), target.begin() + insertPos);
return target;
}
模板
std::vector&VectorAppend(std::vector&target,常量std::vector&source)
{
size_t insertPos=target.size();
resize(target.size()+source.size());
std::copy(source.begin()、source.end()、target.begin()+insertPos);
回报目标;
}
如果您要更改scanDir
,请将其设置为(模板)函数,接受输出迭代器:
template <class OutIt>
void scanDir(const std::string& dirname, OutIt it) {
// ...
// Scan subdir
scanDir(subdir, it);
// ...
}
模板
void scanDir(const std::string和dirname,OutIt){
// ...
//扫描细分
斯堪的纳维亚(细分市场,it);
// ...
}
您将有额外的好处,能够填充所有类型的数据结构,如
std::vector<string> vector;
scanDir(dir1, std::back_inserter(vector));
std::set<string> fileset
scanDir(dir1, std::inserter(fileset, fileset.begin()));
std::vector;
scanDir(dir1,std::back_插入器(向量));
std::set文件集
scanDir(dir1,std::inserter(fileset,fileset.begin());
等等
编辑(见评论…)
要将此函数用于类成员初始化,可以在构造函数中调用它,如中所示
class MyClass {
private:
std::vector<string> m_fileList;
public:
MyClass(const std::string& dirname) {
scanDir(dirname, std::back_inserter(m_fileList);
}
}
class-MyClass{
私人:
std::向量m_文件列表;
公众:
MyClass(常量std::string和dirname){
scanDir(dirname,std::back_插入器(m_文件列表);
}
}
或者使用包装器函数
std::vector<string> scanDir(const std::string& dirname) {
std::vector<string> result;
scanDir(dirname, std::back_inserter(result);
return result;
}
class MyClass {
// Same as above..
MyClass(const std::string& dirname) : m_fileList(scanDir(dirname)) { }
}
std::vector scanDir(const std::string和dirname){
std::向量结果;
scanDir(dirname,std::back_inserter(结果);
返回结果;
}
类MyClass{
//同上。。
MyClass(const std::string和dirname):m_文件列表(scanDir(dirname)){}
}
出于性能(和其他)原因,我更喜欢第一个版本…使用std::list并使用std::list::splice追加
发件人:
该操作不涉及任何元素对象的构造或破坏,除第三个版本外,它是在恒定时间内执行的
矢量文件列表;
向量温度(scanDir(subdirname));
插入(fileList.end(),temp.begin(),temp.end());
我希望这对您有所帮助。这可能不是最简单的解决方案,但是做一些类似于C#的StringBuilder的事情怎么样
制作一个列表
,然后可以将调用scanDir()
得到的所有向量附加到列表中
如果你必须在最后有一个向量,你可以在创建一个新的向量后,分配足够大的向量,这样就不需要调整它的大小,然后组装你的成品
或者,您可以创建一个新类(如果需要,可以从vector派生)然后你只需要让你的迭代器遍历第一个列表中的元素,当它到达最后一个列表中的元素时,只返回container::end,当你到达最后一个列表的末尾时。我知道这并不能直接回答你的问题,但是使用r根据您的基本目标,您可能希望简单地根据boost::filesystem重新实现您的函数。目录迭代器已经是递归的,因此您不需要自己进行递归调用。您可以简单地在迭代器上的循环中填充列表。ls的示例实现如下:
您还可以从(理论上)平台独立性和相对广泛的采用中获得额外的好处(随着采用率的提高,bug会更快地被发现),etc相关:当谈论性能时,第一个问题总是:您衡量了吗?然后是一些琐碎的问题,这是在一个紧密的循环中运行的吗?您的应用程序性能是否至关重要?复制向量与从文件系统检索文件列表相比如何?+1。作为参数传递是我在性能感知中所做的这是我的密码
std::vector<string> vector;
scanDir(dir1, std::back_inserter(vector));
std::set<string> fileset
scanDir(dir1, std::inserter(fileset, fileset.begin()));
class MyClass {
private:
std::vector<string> m_fileList;
public:
MyClass(const std::string& dirname) {
scanDir(dirname, std::back_inserter(m_fileList);
}
}
std::vector<string> scanDir(const std::string& dirname) {
std::vector<string> result;
scanDir(dirname, std::back_inserter(result);
return result;
}
class MyClass {
// Same as above..
MyClass(const std::string& dirname) : m_fileList(scanDir(dirname)) { }
}
vector<string> fileList;
vector<string> temp( scanDir(subdirname) );
fileList.insert(fileList.end(), temp.begin(), temp.end());