代码之家  ›  专栏  ›  技术社区  ›  iBug

在C++中仍然使用va_列表吗?还是鼓励使用模板<类型名。。。T> 什么?

  •  10
  • iBug  · 技术社区  · 7 年前

    在C语言中,定义可变长度参数的唯一方法是用省略号声明其原型并使用 va_list va_start , va_arg , va_end printf scanf 系列do。

    在C++11中,引入了一种新方法,如下所示。

    template <typename T, typename... MoreT>
    void func(T arg, MoreT... args){
        // Do some stuff
        func(args);
    }
    

    每种方法的优点和缺点是什么?在C++中是不鼓励使用还是鼓励使用它们?

    4 回复  |  直到 3 年前
        1
  •  6
  •   Nir Friedman    7 年前

    C型变量函数是 沉重地 在C++中不鼓励。风格各异,但写这类函数会让你在某些圈子里(包括我的圈子)晕头转向,除非有真正特殊的原因。

    就权衡而言,C型变量函数是完全类型不安全的。您可以尝试从变量包中提取错误类型的内容,这将导致segfault。C++可变模板是强类型的,所以这是不可能的(当然,除非你用reinterpret_cast或类似的方法强制它)。

        2
  •  4
  •   NP Rooski Z    7 年前

    C++力求比C更安全。 nullptr , enum class 提供更多类型安全代码。编译器是您更聪明的朋友。

    当参数处于 va_list 运行时

        3
  •  2
  •   zneak    7 年前

    可变参数函数没有太多好处,但也有一些好处。

    C++可变模板是类型安全的,而C可变函数不是。这意味着编译器通常不会强制函数传递给变量函数的参数类型。GCC和Clang支持一些处理常见情况的属性:

    • __attribute__((format())) printf scanf 并在参数与您传递的格式字符串不匹配时发出警告;
    • __attribute__((sentinel(N))) 告诉编译器最后一个可变参数应该是前哨值。

    搞砸的可能性仍然很大。例如 open 要求 mask O_CREAT 是指定的,但经常被忘记,这两个 __attribute__ 扩展可以解决这个问题。

    标准允许但不要求实现允许将非POD类型传递给C变量函数;当它工作时,语义是由实现定义的。这意味着,如果希望代码跨平台,就不应该这样做。

        4
  •  -1
  •   pepero    7 年前

    c varadic函数是特定于实现的,很可能是宏,因此它们没有类型安全性。更多信息。 varadic ,例如。

    #define va_arg(list, mode) ((mode *)(list = (char *)list + sizeof(mode)))[-1]
    

    va_list, va_start, va_arg, va_end.
    

    另一方面,c++1x提供了更多的工具来解决这个问题,例如,对于类型特征,您可以检查它是否是整数,初始化器列表以进行扩展,等等。总之,您可以做很多强大的工作