我在这里有一个问题:我要编写一个函数,该函数以递归方式打印矢量的元素,因此不允许循环。
我尝试了这段代码,但在运行时崩溃:
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
int main(){
vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v, v.begin());
}
如果我运行该程序,则会显示断言对话框!?
答案 0 :(得分:2)
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
ivec
参数按值传递。这两个参数均按值传递。通过值传递意味着这些函数在内部是原始参数的 副本 。
您的main()
调用此递归函数,并将其向量和向量的开始迭代器传递给它。但是,由于所有参数都是按值传递的,因此函数的每个递归迭代都将迭代器与完全不同的向量的end()
进行比较。未定义的行为。
您显然忘记了通过参考传递矢量。的第一个参数应为const std::vector<int> &ivec
。
答案 1 :(得分:1)
调用print
时,将按值传递向量。这意味着它每次都会创建一个全新的向量,但是迭代器仍然来自原始向量。因为迭代器来自不同的向量,所以测试it == ivec.end()
总是会失败。
我们可以通过仅通过const引用传递ivec
来解决此问题:
void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it)
{
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
代码正常工作!
答案 2 :(得分:1)
您必须通过引用传递向量,以便避免重复,从而保证将迭代器与同一向量的迭代器进行比较,而不能与其他向量进行比较:
void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) {
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
int main(){
vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v, v.begin()); // ok
vector<int>::iterator it = v.begin();
auto v2{ v };
if (it == v.begin())
cout << "it = v.begin()" << endl;
if (it == v2.begin()) // causes crash
cout << "it =v2.begin()" << endl;
}
答案 3 :(得分:0)
无需将两个参数传递给print函数。如果矢量的长度为零,则不打印任何内容。
如果向量的长度为1,则打印该元素。
如果矢量的长度大于1,则(递归)打印一个较小的不包含最后一个字符的矢量,然后打印最后一个字符。
是的,这将为每次递归创建向量的副本,但是我想这对我来说更像递归。在每个循环上增加指针的感觉并不像递归。
#include <iostream>
#include <vector>
void print(const std::vector<int> vec) {
if (!vec.size())
return;
else {
print(std::vector<int>(vec.begin(), vec.end() - 1));
std::cout << " " << *(vec.end() - 1);
}
}
int main(){
std::vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v);
}
答案 4 :(得分:0)
如果只需要打印矢量,我认为一个更优雅的解决方案是使用迭代器。
#include <iostream>
#include <vector>
using namespace std;
void print_vector(vector<int>::iterator it, const vector<int>::iterator &end)
{
if(it == end) {
cout << '\n';
return;
}
cout << *it << " ";
print_vector(++it, end);
}
int main() {
vector<int> v = {1,2,3,4,5,6,7,8,9};
print_vector(v.begin(), v.end());
return 0;
}
如果您想在其他结构中重用该功能(可能给朋友或老师留下深刻印象),则可以使用模板。
#include <iostream>
#include <set>
#include <vector>
using namespace std;
template<class TContainer>
void print_structure(typename TContainer::iterator it, const typename TContainer::iterator end)
{
if(it == end) {
cout << '\n';
return;
}
cout << *it << " ";
print_structure<TContainer>(++it, end);
}
int main() {
vector<int> vi = {1,2,3,4,5,6,7,8,9};
print_structure<vector<int>>(vi.begin(), vi.end());
vector<double> vd = {1.2, 3.4, 5.6, 7.8, 9.0};
print_structure<vector<double>>(vd.begin(), vd.end());
set<int> si = {10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 30};
print_structure<set<int>>(si.begin(), si.end());
set<double> sd = {10.10, 10.10, 20.20, 20.20, 30.30, 3.0};
print_structure<set<double>>(sd.begin(), sd.end());
return 0;
}
杀死蚊子看起来像火箭筒吗?就是这样!但这是非常疯狂的吗?!