带有可变参数的c++方法(..)报告不正确的参数值

C++ method with variable arguments (...) reporting incorrect arg values

本文关键字:参数 报告 不正确 c++ 变参 方法      更新时间:2023-10-16

我在将变量参数正确传递给方法时遇到了麻烦-该方法旨在在加权分布中选择随机值并返回所选结果的索引。

一个例子是:

int pickupType = randomManager->ByWeights( 3, 0.60f, 0.20f, 0.20f );
switch( pickupType ) {
    // ... pickupType should be 0 to 2, which we can then branch on
}

函数定义如下:

#include <cstdarg>
int RandomManager::ByWeights( int weightCount, ... ) {
    va_list argList;
    // Get the total of all weights
    va_start( argList, weightCount );
    float weightTotal = 0;
    for ( int i = 0; i < weightCount; i++ ) {
        weightTotal += va_arg( argList, float );
    }
    va_end( argList );
    // Roll a number in that range
    // ... (further processing - problem occurs above)
}

当我在调试器中运行它时,对va_arg( argList, float )的调用返回垃圾值( 2.0, 1.77499998, -1.08420217e-019 ),而不是在( 0.60f, 0.20f, 0.20f )中传递的值。

你知道我做错了什么吗?据我所知,我完全遵循了规范。我一直使用http://www.cplusplus.com/reference/cstdarg/作为参考

在variadic函数中,float形参将被转换为double类型。试着

weightTotal += va_arg( argList, double );

问题是float经过...后被提升为double

所以你的循环应该是
for ( int i = 0; i < weightCount; i++ ) {
    weightTotal += va_arg( argList, double );
}

如果你正在使用c++,这不是真正正确的方式来做事情了。可变参数模板比可变参数(来自c)更好。下面是我不久前为类做的可变和的一个更好的例子。

#include <iostream>
namespace cs540 {
    template <typename T>
    const T & sum(const T & v) {
        return v;
    }
    template <typename T, typename T2, typename ... Ts>
    T sum(const T & v, const T2 & w, const Ts & ... params) {
        return sum(w+v,params...);
    }
}
int main() {
    using namespace cs540;
    using namespace std;
    cout << sum(1.1,2,3,4,6,8,9,1.1) << endl;
}
可变模板是类型安全的,并且产生更可读的无错误代码。