基于单例模式的定时器链接器错误
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
}
第一次尝试写单例。这是一个与一个函数一起工作的计时器,用于处理计时器的启动和停止以及打印结果。 编译时,我遇到这样的链接器错误:
:-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
}