#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <random>
#include <map>
#include <math.h>
#include <cstring>
using namespace std;
class MathClass {
private:
size_t current_capacity;
double* logfact;
bool inited = false;
MathClass() {
current_capacity = 0;
logfact = new double[1];
logfact[0] = 0;
}
void calculateLogFact(int n) {
if (current_capacity >= n) return;
double* newLogfact = new double[n 1];
for (int i=0; i<=current_capacity; i ) newLogfact[i] = logfact[i];
for (int i=current_capacity 1; i<=n; i ) newLogfact[i] = newLogfact[i-1] log(double(i));
delete[] logfact;
logfact = newLogfact;
}
double factorial(int n) {
cout << "n = " << n << "\n";
calculateLogFact(n);
for (int i=0; i<=n; i ) cout << int64_t(round(exp(logfact[i]))) << " ";
cout << "\n";
return exp(logfact[n]);
}
public:
static double factorial2n(int n) {
static MathClass singleton;
return singleton.factorial(2*n);
}
};
int main(int argc, char** argv)
{
cout << MathClass::factorial2n(10) << "\n";
return 0;
}
我的庫需要使用一個昂貴的函式,該函式需要在使用前初始化一次(預先計算一些昂貴的值,這樣我們就不必每次都計算它們)。目前,我為此使用上面的單例方法。
但是,有兩個問題:
- 多執行緒:如果 2 個不同的執行緒呼叫此函式,這將導致競爭條件。
- 人們不喜歡單身人士
- 其他我不知道的問題
我可以使用什么其他設計來解決這個問題?預先計算值是必須的,因為這個函式需要很快。
uj5u.com熱心網友回復:
MathClass我同意評論:為什么要隱藏用戶快取結果的事實?作為潛在用戶,我看不到真正的好處,而是看到潛在的混亂。如果我想重用之前存盤在實體中的快取結果,我可以這樣做。你不需要將整個類包裝在一個單例中讓我啟用它。當您可以使用std::vector.
簡而言之:使用單例的替代方法是不使用單例。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <random>
#include <map>
#include <math.h>
#include <cstring>
using namespace std;
class MathClass {
private:
size_t current_capacity;
std::vector<double> logfact;
bool inited = false;
void calculateLogFact(int n) {
if (logfact.size() >= n) return;
auto old_size= logfact.size();
logfact.resize(n);
for (int i=old_size; i<n; i ) logfact.push_back(logfact.back() log(double(i)));
}
double factorial(int n) {
cout << "n = " << n << "\n";
calculateLogFact(n);
for (int i=0; i<=n; i ) cout << int64_t(round(exp(logfact[i]))) << " ";
cout << "\n";
return exp(logfact[n]);
}
public:
MathClass() {
logfact.push_back(0);
}
double factorial2n(int n) {
return factorial(2*n);
}
};
void foo(MathClass& mc) { // some function using previously calculated results
std::cout << mc.factorial2n(2);
}
int main(int argc, char** argv)
{
MathClass mc;
cout << mc.factorial2n(10) << "\n";
foo(mc);
}
我不確定數學是否正確,我沒有費心去檢查。此外inited,大多數包含似乎未使用。
關于“多執行緒:如果 2 個不同的執行緒呼叫此函式,這將導致競爭條件。” 我也不會費心將執行緒安全融入型別本身。當我想單執行緒使用它時,我不需要執行緒安全,也不想為此付費。當我想在多執行緒中使用它時,我可以使用我自己的std::mutex來保護對mc實體的訪問。
PS:坦率地說,我認為整個問題是由誤解引起的。您MathClass不是“僅功能”類。它是一個具有狀態和成員函式的類,就像任何其他類一樣。“誤解”是向用戶隱藏狀態并假裝沒有狀態,而實際上有狀態。使用此類時,我希望控制我可以查詢哪些結果,因為它們已經被快取并且需要首先計算哪些結果。換句話說,我會提供對類狀態的更多訪問,而不是更少。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/424313.html
上一篇:如何將每個字串字符插入二維陣列
下一篇:使用遞回的int陣列的排列
