基于单例模式的定时器链接器错误

Linker error on Timer based on Singleton pattern

第一次尝试写单例。这是一个与一个函数一起工作的计时器,用于处理计时器的启动和停止以及打印结果。 编译时,我遇到这样的链接器错误:

:-1: ошибка: CMakeFiles/some_algorithms.dir/timer_singleton.cpp.obj:timer_singleton.cpp:(.rdata$.refptr._ZN15timer_singleton7counterE[.refptr._ZN15timer_singleton7counterE]+0x0): undefined reference to `timer_singleton::counter'

导致此错误的原因是什么,我该如何解决?

这是我的源代码:

timer_singleton.h

#ifndef TIMER_SINGLETON_H
#define TIMER_SINGLETON_H
#pragma once
#include <iostream>
#include <chrono>

class timer_singleton
{
public:
    timer_singleton(timer_singleton & other) = delete;
    void operator=(const timer_singleton& other) = delete;
    static timer_singleton * getInstance();
    static void hit_the_clock();
private:
    timer_singleton();
    static timer_singleton * instance;
    static std::chrono::high_resolution_clock clock;
    static std::chrono::high_resolution_clock::time_point start;
    static std::chrono::high_resolution_clock::time_point stop;
    static size_t counter;
};

#endif // TIMER_SINGLETON_H

timer_singleton.cpp

#include "timer_singleton.h"

timer_singleton::timer_singleton()
{
    clock = std::chrono::high_resolution_clock();
    start = clock.now();
    stop = clock.now();
    counter = 0;
}

timer_singleton * timer_singleton::getInstance()
{
    if (instance == nullptr)
    {
        instance = new timer_singleton();
    }
    return instance;
}

void timer_singleton::hit_the_clock()
{

    if (counter % 2 == 1)
    {
        // Clocks start ticking
        start = clock.now();
        ++counter;
    }
    else
    {
        // Clocks stop ticking and print time measured time
        stop = clock.now();
        auto duration =  std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
        std::cout << "Measured time = " << duration.count() << " microseconds" << std::endl;
        ++counter;
    }

}

main.cpp

#include "timer_singleton.h"
// ...

timer_singleton * timer = timer_singleton::getInstance();
timer->hit_the_clock();
// some calculations
timer->hit_the_clock();

问题:大多数 non-constant static 成员需要在 class 定义之外定义,以便获得将由所有人共享的 one-and-only-one 实例class 个实例。通常这意味着在 timer_singleton.cpp 中你必须添加

timer_singleton::counter = 0; // allocate and initialize

但是...

单例实际上已经 static 所以唯一的静态成员应该是获取实例的函数。这使整个问题消失了。

新代码以及对其他有用更改的评论:

class timer_singleton
{
public:
    timer_singleton(timer_singleton &other) = delete;
    void operator=(const timer_singleton &other) = delete;
    static timer_singleton* getInstance();
    void hit_the_clock(); // shouldn't be static
private:
    timer_singleton();

    // None of these should have been static
    std::chrono::high_resolution_clock clock; // This clock could jump around, 
                                              // including backward, in time. 
                                              // Safer with a steady_clock
    std::chrono::high_resolution_clock::time_point start;
    std::chrono::high_resolution_clock::time_point stop;
    size_t counter;
};


timer_singleton::timer_singleton():
        start(clock.now()),
        stop(start), // guaranteed to be same as start
        counter(0)
{ // assignments replaced with initializations in member initializer list
}

timer_singleton* timer_singleton::getInstance()
{ // now using Meyers singelton
    static timer_singleton instance;

    return &instance; // consider adjusting to return a reference. 
                      // Often a bit cleaner thanks to the no null guarantee
}

void timer_singleton::hit_the_clock()
{
    auto now = clock.now(); // if timing is critical, the first thing
                            // you do is get the current time.
    //if (counter % 2 == 1) // remember counter starts at 0, so first hit
                            // would stop, not start, the timer.
    if (counter % 2 == 0)
    {
        // Clocks start ticking
        start = now;
    }
    else
    {
        // Clocks stop ticking and print time measured time
        stop = now;
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
        std::cout << "Measured time = " << duration.count() << " microseconds" << std::endl;
    }
    ++counter; // don't repeat yourself
}