具有多个被识别为只有一个成员的结构的列表

List with many structs recognized as having just one member

本文关键字:成员 有一个 结构 列表 识别      更新时间:2023-10-16

在下面的程序中,我将包含许多不同日期的data传递给函数GetAvgDayVolm(),然后该函数中的cout语句输出1

但是它应该输出比1更多的数据,因为data中有不止一个不同的日期。虽然程序根本没有进入if语句,但看起来curTime已经更改。你看到什么不对吗?

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;
}

在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,或者先保存结果。

问题是您使用的是从gmtime()函数返回的指针,它基本上是每个使用时间函数的调用程序共享的公共内存块。解决这个问题的方法是将值复制出去(通过取消引用返回的指针),而不是保留指针的副本。

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

此外,我会考虑将函数参数从指针更改为常量引用,因为它总是被假设存在,并且不会被函数修改。

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

// 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??
}
相关文章: