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



第一次尝试写Singleton。这是一个定时器,与一个函数处理定时器的开始和停止,也打印结果。当编译时,我得到这样的链接器错误:

:-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();

问题:大多数非常量static成员需要在类定义之外定义,以便获得将由所有类实例共享的一个且仅一个实例。通常,这意味着在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
}

最新更新