c++可变参数数

C++ variable number of arguments

本文关键字:数数 变参 c++      更新时间:2023-10-16

我需要定义一个可以接受可变数量的参数的虚拟函数,问题是c风格的省略符不适用于非pod类型,我有有限的内存量(2KB),所以我试图避免分配临时对象只是为了传递给函数,所有参数将是相同的类型(自定义共享指针),我也没有访问stl或boost。是否有c++技巧允许我调用带有变量参数的函数?

假设您的参数类型是类Arg,您可以尝试:

class ArgUser {
public:
    // syntactic sugar:
    void method() { // nullary
        doMethod();
    }
    void method( const Arg & a1 ) { // unary
        doMethod( &a1 );
    }
    void method( const Arg & a1, const Arg & a2 ) { // binary
        doMethod( &a1, &a2 );
    }
    // and so on, until max arity
private:
    // actual virtual function:
    virtual void doMethod( const Arg * a1=0, const Arg * a2=0 /*etc, until max arity */ ) = 0;
};

该解决方案具有以下属性:

  1. 它使用NVI习惯用法
  2. 使用指针是因为它们不会导致创建临时变量,即使是未使用的默认参数。
  3. 在(内联)包装器方法中封装了难看的指针杂耍。

另一种解决方案(可能更有效,也可能不更有效)是:

class AltArgUser {
public:
    // syntactic sugar:
    void method() { // nullary
        doMethod( 0, 0 );
    }
    void method( const Arg & a1 ) { // unary
        doMethod( &&a1, 1 );
    }
    void method( const Arg & a1, const Arg & a2 ) { // binary
        const Arg * args[] = { &a1, &a2 };
        doMethod( args, 2 );
    }
    // and so on, until max arity
private:
    // actual virtual function:
    virtual void doMethod( const Arg * args[], size_t numArgs ) = 0;
};

要决定使用哪一个,您需要研究在您的特定平台上为每个方法生成的汇编程序。无论选择什么,都应该保留包装器函数。

定义一个函数,接受一个指向形参数组的指针和一个表示数组大小的形参。

同样,如果你不想硬编码一个固定大小的数组,你可以使用alloca来分配堆栈上的存储空间,而不用担心访问堆或调用free

指向共享指针的指针是pod,您可以更改原型以使用每个参数的内存位置吗?像这样(未测试):

shared_ptr arg1;
shared_ptr arg2;
ClassWithVirtualFunction c;
c.yourVirtualFunction(&arg1, &arg2, NULL);
ClassWithVirtualFunction
{
    virtual void yourVirtualFunction(shared_ptr* first, ...)
    {
        va_list marker;
        va_start( marker, first );
        shared_ptr* current=first;
        while (current != NULL)
        {
            /* do stuff with *current */
            current = va_arg( marker, shared_ptr* );
        }
        va_end(marker);
    }
}

您可以使用一个固定数组,它实际上比可变数量的参数更快,占用的空间更少。因为可变数量的参数做了很多检查和安全。

mytype arr[3];
arr[0] = a;
// etc
myfunction(arr, 3);

也许如果你已经有了自己的自定义指针类型,你可以定义自己的基本链表类(毕竟这是c++),最后一个"指向next的指针"为NULL,以表示变量数量的结束

像这样:

class MyPointer
{
  // Whatever you have/want
};
class MyArgs
{
  static int nargs; // Static class variable for total number of args
  MyPointer* data;
  MyArgs*    next; 
  public:
  MyArgs(int nargs)
  {  
    // Some funky constructor to create required number of args...
  }  
  MyPointer* operator[](int at)
  {  
    // Nice overloaded operator for you to get at data
  }  
};
class PlanToDoStuff
{
  public:
  virtual void foobar(MyArgs)=0;
};
class ActuallyDoStuff: public PlanToDoStuff
{
  public:
  void foobar(MyArgs)
  {  
    // Do stuff with args...
  }  
};
int main()
{
    MyArgs args(3);
    ActuallyDoStuff dosomething;
    dosomething.foobar(args);
}