列出许多结构被认为只有一个成员

时间:2016-03-22 03:07:10

标签: c++

在以下程序中,我将包含许多不同日期的data传递给函数GetAvgDayVolm(),此函数中的cout语句然后输出1。< / p>

但它的输出应超过1,因为data中有多个不同的日期。虽然程序根本没有进入curTime语句,但看起来if已更改。你看错了吗?

long int GetAvgDayVolm(list<struct DataPoint>* data)
{
    long long int totalVolm = 0;
    long int numOfDays = 1;
    struct DataPoint dp = (*data).front();
    time_t rawTime2 = dp.timeStamp;
    time_t rawTime  = 0;
    struct tm* curTime = gmtime(&rawTime2);

    struct tm* movingTime = new struct tm ();

    for(list<struct DataPoint>::iterator it = (*data).begin(); it != (*data).end(); ++it)
    {
        rawTime = (*it).timeStamp;
        movingTime = gmtime(&rawTime);
        totalVolm += (*it).volm;

        if(curTime->tm_mday != movingTime->tm_mday || 
           curTime->tm_mon  != movingTime->tm_mon || 
           curTime->tm_year != movingTime->tm_year)
        {
            numOfDays = numOfDays + 1;
            curTime = movingTime;
        }
    }

    cout<<numOfDays<<endl;
    return 0;
}

2 个答案:

答案 0 :(得分:3)

在gmtime联机帮助页中,NOTES部分说:

The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe

所以在你的代码中,curTime和movingTime指向相同的静态数据区,你应该使用gmtime_r,或者只保存结果。

答案 1 :(得分:2)

问题是你正在使用从gmtime()函数返回的指针,它基本上是一个公共的内存块,每个调用者使用时间函数共享。修复它的方法是复制值(通过解除引用返回的指针)而不是保留指针的副本。

在多线程环境中,您还需要采取进一步的预防措施。使用其中一个线程安全版本(gmtime_r / gmtime_s)或使用互斥锁(慢速)同步访问。

此外,我会考虑将您的函数参数从指针更改为 const引用,因为它始终假定存在且不会被函数修改。

以下是您的功能的可能解决方案:

// pass by const reference if possible because
// the list is assumed to exist and is never modified
long int GetAvgDayVolm(const list<DataPoint>& data)
{
    if(data.empty()) // possible crash later without this check
        return 0;

    long long int totalVolm = 0;
    long int numOfDays = 1;
    DataPoint dp = data.front(); // REQUIRES list contains at least one element
    time_t rawTime2 = dp.timeStamp;
    time_t rawTime  = 0;

    // don't use pointer here, dereference the
    // returned value
    std::tm curTime = *gmtime(&rawTime2);

    // no need for pointer here - dereference the
    // return value of gmtime() instead
    std::tm movingTime;

    for(list<DataPoint>::const_iterator it = data.begin(); it != data.end(); ++it)
    {
        rawTime = it->timeStamp;
        movingTime = *gmtime(&rawTime);
        totalVolm += it->volm;

        if(curTime.tm_mday != movingTime.tm_mday ||
           curTime.tm_mon  != movingTime.tm_mon ||
           curTime.tm_year != movingTime.tm_year)
        {
            numOfDays = numOfDays + 1;
            curTime = movingTime;
        }
    }

    cout<<numOfDays<<endl;
    return 0; // is this correct??
}