我遇到了va_list的问题。我在构造函数中使用它来获取意外数量的数据到我的对象。有问题的代码在那里:
#include <cstdarg>
#include <iostream>
using namespace std;
class DATA{
private:
int length;
int* tab;
public:
DATA():tab(NULL), length(0){};
DATA(int x, ...):length(x+1){
va_list ap;
va_start(ap, x);
tab=new int[length];
for(int i=0; i<length; ++i){
tab[i]=va_arg(ap, int);
}
va_end(ap);
}
void showthem()const{
if(tab!=NULL){
int x;
for(x=0; x<length-1; ++x){
cout<<tab[x]<<", ";
}
cout<<tab[x];
}
}
}
ostream & operator<<(ostream & out, const DATA & x){
x.showthem();
return out;
}
int main(){
int table [] = {5,1,2,3,4,5,6};
DATA x1(*table);
DATA x2(4,1,2,3,4,5);
cout << x1 << endl;
cout << x2 << endl;
}
当我通过编写所有参数自然地创建对象时它没关系,但是当我尝试通过表格来制作它时它会产生问题。 我在课程标签中得到了意想不到的数据。
我想我做错了什么。最糟糕的方式 - 我甚至可以通过* table制作这样的对象吗?我给构造函数一些整数,所以它应该工作...
答案 0 :(得分:1)
KIIV钉了它。 std::initializer_list
(documentation linked here)正是OP所需要的。
忘记变量参数列表。它们允许以不同的方式进行难以调试的程序。例如,
DATA x2(41,2,3,4,5)
糟糕!错过了一个逗号,并且会在堆栈中读出超出范围的waaaaaay!或者
DATA x2(5, 1,2,3,4,"I am the very model of a modern major-general...")
哪个更易于发现,但仍然可以编译,因为编译器不知道或不关心varadic函数允许的类型。
但initializer_list<int>
只允许int
,您无需指定int
的数量。那里有一个更小的潜在错误!
修复一些明显的错误步骤并忽略elephant in the room, std::vector
,暂时我们得到的东西看起来像
#include <initializer_list>
#include <iostream>
class DATA{
private:
int length;
int* tab;
public:
DATA(std::initializer_list<int> vals):
length(vals.size()), tab(new int[length])
{
int index = 0;
for(int val: vals){
tab[index]=val;
index++;
}
}
DATA(const DATA& src) = delete;
DATA& operator=(const DATA& src) = delete;
friend std::ostream & operator<<(std::ostream & out, const DATA & x){
if(x.tab!=NULL){
int index=0;
out<<x.tab[index];
for(index++; index < x.length; ++index){
out<<", "<<x.tab[index];
}
}
return out;
}
};
int main(){
DATA x1({1,2,3,4,5});
std::cout << x1 << std::endl;
}
请注意{}
中的DATA x1({1,2,3,4,5});
大括号。这会建立列表。列表知道它有多大,所以你不必告诉函数有多少项目即将来临。
请注意,我已删除了复制构造函数和赋值运算符。这是因为三法则。 What is The Rule of Three?阅读链接并了解相关信息。它将为您节省大量未来的调试时间。
这也很容易模板化:
template <class TYPE>
class DATA{
private:
int length;
TYPE* tab;
public:
DATA(std::initializer_list<TYPE> vals):
length(vals.size()), tab(new TYPE[length])
{
int index = 0;
for(const TYPE& val: vals){
tab[index]=val;
index++;
}
}
DATA(const DATA& src) = delete;
DATA& operator=(const DATA& src) = delete;
friend std::ostream & operator<<(std::ostream & out, const DATA & x){
if(x.tab!=NULL){
int index=0;
out<<x.tab[index];
for(index++; index < x.length; ++index){
out<<", "<<x.tab[index];
}
}
return out;
}
};
int main(){
DATA<int> x1({1,2,3,4,5});
DATA<std::string> x2({"I", "am", "the", "very", "model", "of", "a", "modern", "major-general"});
std::cout << x1 << std::endl;
std::cout << x2 << std::endl;
}