C++ varargs - 我是如何使用它们的还是它们不好?有没有好的替代方案?

Int*_*ble 5 c++ variadic-functions visual-studio-2010 c++11

这样做的最终目标是拥有一个函数,该函数可以采用可变数量的某种类型(相同类型,而不是不同类型)的参数,这些参数可以在函数调用时声明。

当我使用 Visual Studio 2010 时,我不能这样做:

MyFunction({1,2,3});
Run Code Online (Sandbox Code Playgroud)

在之前回答的一个问题中,我发现我可以使用boost::assign::list_of(),但是后来我发现如果您尝试仅将一个参数传递给它,这似乎存在某种错误

所以我做了更多的搜索,发现我可以使用可变参数函数来实现我的目标。

void TestFunction2<int>(int count, ...)
{}
Run Code Online (Sandbox Code Playgroud)

但是,我想按类型限制它,所以最终发现我可以用模板来做到这一点:

template <class T>
void TestFunction(const T& count, ...);

template <>
void TestFunction<int>(const int& count, ...);
Run Code Online (Sandbox Code Playgroud)

不幸的是, varargs 之类的东西va_list显然不喜欢引用。我看到的限制此类类型的示例使用了 const 引用。如果我删除 count 参数的 const 引用方面,它会按我的意愿工作,但我不知道这是否会导致可怕的副作用,或者这整个可变参数是否是一个坏主意首先。

所以我想我的问题是,我在上面最后一个例子中所做的是好还是坏?如果它很糟糕,那么有什么好的选择,这样我就可以调用一个带有一个或多个内嵌参数的函数,比如int参数?

Jas*_*ick 0

编辑:

还有一个解决方案...如果您的编译器的 IDE部分支持C++11,您可以std::vector在调用时初始化 a ,即

template <typename T>
void TestFunction(std::vector<T> vect)
{
....
}

....

TestFunction(std::vector<int>{1,2,3});
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是当函数超出范围时,STL 会自动释放分配的内存。

如果这不起作用,你可以求助于两线......

template <typename T>
void TestFunction(std::vector<T> vect)
{
....
}

....
std::vector<int> tmp(1,2,3);
TestFunction(tmp);
Run Code Online (Sandbox Code Playgroud)

最大的缺点是,内存位于堆栈上,直到您离开该范围(或显式地将向量大小调整为零长度)。

两种方法都有一些优点......计数是内置的,您可以访问其他有用的成员函数或附属方法(例如std::sort)。

......................................

为什么不使用变量参数?例如,请参阅此处的答案...
在 C API 中使用 varargs 来设置键值对是个好主意吗?

在不C+11兼容的编译器(例如您的 IDE)上,您可以尝试...

template <typename T>
TestFunction(const unsigned int count, T * arr)

TestFunction<std::string>(10, new string[] {"One", "Two", "Three"});
Run Code Online (Sandbox Code Playgroud)

(听起来你不能在 IDE 中使用它,但是......)如果你确信你只在现代机器上进行编译并且主要使用简单类型,那么这是最好/最符合标准的解决方案......

截至C++11您可以使用std::initializer以下内容std::vector

#include<vector>

template <typename T>
void TestFunction(const std::initializer_list<T>& v)
{ }

int main()
{
    TestFunction<double>({1.0, 2.0});
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

……………………

...但是这需要您的编译器,C+11因此它不完全可移植。对于简单类型以外的任何类型,它也变得更难阅读。

我知道你说的是on the functioncall,但你可能想从编码方法的可读性和易用性角度重新思考这一点。

我同意你的部分方法——你想要的是使用一个template函数(这处理变量type)。在调用之前,将相同类型元素的集合初始化为临时标准 C 数组或 / std::vectorstd::listSTL 的数组包装器)。

http://www.cplusplus.com/doc/tutorial/templates/
http://www.cplusplus.com/reference/vector/
http://www.cplusplus.com/reference/list/

它的代码行数更多,但更具可读性和标准化。

IE

而不是...

MyFunction({1,2,3});
Run Code Online (Sandbox Code Playgroud)

使用:

template <typename T>
void TestFunction(const int count, T * arr)
{
  for (unsigned int i = 0; i < count; i++)
  {
    .... arr[i] ... ; //do stuff
    ...
  }
}

int main()
{
  int * myArr = {1,2,3};
  TestFuntion<int>(3, myArr);
}
Run Code Online (Sandbox Code Playgroud)

...或者...

#include <vector>
template <typename T>
void TestFunction(std::vector<T> vect)
{
  for (unsigned int i = 0; i < vect.size(); i++)
  {
    .... vect[i] ... ; //do stuff
    ...
  }
}

int main()
{
  std::vector<int> myVect;
  myVect.push_back(1);
  myVect.push_back(2);
  myVect.push_back(3);
  TestFuntion<int>(myVect);
}
Run Code Online (Sandbox Code Playgroud)

std::list也将是完全可以接受的,并且可能表现更好,具体取决于您的用例。