gpt4 book ai didi

c++ - 对象似乎没有通过C++的引用传递

转载 作者:行者123 更新时间:2023-12-01 14:52:40 25 4
gpt4 key购买 nike

编辑:发现问题是当传递到MCEngine函数和下面显示的SimulationEngine类中时,Wrapper类正在创建BSCallFunction的副本。考虑到这一点,我仍然需要弄清楚如何使程序按我的意愿做,如问题中所详述。评论部分包含到目前为止的发现。

class SimulationEngine
{
public:
SimulationEngine(double horizon, const Wrapper<valuationFunction>& theFunction_, RiskFactor simulatedRiskFactor);
virtual void DoOnePath(double vol, double normvariate) = 0;
virtual SimulationEngine* clone() const = 0;
const double GetHorizon();
Wrapper<valuationFunction>& GetFunction();
RiskFactor simulatedRiskFactor;
protected:
double horizon;
Wrapper<valuationFunction> theFunction;
};

在主类中,我正在创建此对象:
    BSCallFunction ThisBsCall(nominal, S0, r, d, impvol, TTM, Strike);

我要传入两个类(从同一个基类派生),这两个类将更改其某些值(例如S0和r)。
    OneStepBSEngine BSSimulation(timeHorizon, zeroDrift, ThisBsCall, RiskFactor::equity);
OneStepBrownianMotionEngine ShortRateSimulation(timeHorizon, zeroDrift, ThisBsCall, RiskFactor::interest_rate);

我希望两个类都更改同一对象的值,以便最终得到具有不同r和S0的ThisBsCall。

这些类具有以下结构:
class OneStepBrownianMotionEngine : public SimulationEngine
{
public:
OneStepBrownianMotionEngine(double horizon_, double drift_,const Wrapper<valuationFunction>& theFunction_, RiskFactor simulatedRiskFactor_);
virtual SimulationEngine* clone() const;
void DoOnePath(double vol, double normvariate);
private:
double drift;
};

OneStepBrownianMotionEngine::OneStepBrownianMotionEngine(double horizon_, double drift_,const Wrapper<valuationFunction>& theFunction_, RiskFactor simulatedRiskFactor_) : SimulationEngine(horizon_, theFunction_, simulatedRiskFactor_), drift(drift_)
{
}

我通过const引用传递“ThisBsCall”对象的位置。

回到我的主类中,然后我将创建对象MCEngine并使用将通过上述Engine类更改r和S0值的函数,Enginevector只是两个Engine类的 vector :
MCEngine VAREngine(EngineVector, covmat);
VAREngine.DoSimulation(gathererCombiner, NumberOfPaths);

我也通过const引用传递enginevector,如下所示:
MCEngine(const std::vector<Wrapper<SimulationEngine>>& EngineVector, std::vector<std::vector<double>> covMatrix_);

我不确定是否重要,但是在MCEngine类中使用的构造函数和函数如下所示:
MCEngine::MCEngine(const std::vector< Wrapper<SimulationEngine>>& EngineVector_, std::vector<std::vector<double>> covMatrix_)
: cholMatrix(Cholesky_Decomposition(covMatrix_)), EngineVector(EngineVector_), V(0)
{
}

void MCEngine::DoSimulation(StatisticsMC& TheGatherer, unsigned long NumberOfPaths)
{
UpdateTTM();
double thisPortfolioValue;
for (unsigned long i = 0; i < NumberOfPaths; ++i)
{
std::vector<Wrapper<SimulationEngine>> tmpEngineVector(EngineVector); //save the origianl EngineVector to use on next path
//create vector of correlated normal variats with cholezky decompositon
MJArray corrNormVariates(cholMatrix.size());
corrNormVariates = 0;
MJArray NormVariates(cholMatrix.size());
for (unsigned long i = 0; i < cholMatrix.size(); i++)
{
NormVariates[i] = GetOneGaussianByBoxMuller();
for (unsigned long j = 0; j < cholMatrix[i].size(); j++) {
corrNormVariates[i] += cholMatrix[i][j] * NormVariates[j];
}
corrNormVariates[i] /= cholMatrix[i][i]; //normalize the random variates
}
//use each one for simulation with spotvector/volvector
for (unsigned long j = 0; j < EngineVector.size(); ++j)
{
EngineVector[j]->DoOnePath(cholMatrix[j][j], corrNormVariates[j]); //updates the riskfactors for the positions
}
ValuePortfolio();
thisPortfolioValue = GetPortfolioValue();
TheGatherer.DumpOneResult(thisPortfolioValue);
EngineVector = tmpEngineVector;
}
}

现在我的问题是,当我查看2个BSCallFunction对象(我​​希望它是相同的ThisBsCall)时,它们的S0和r值不同,所以似乎在某个时候我复制了该对象并更改了r或S0的值副本而不是原始副本,然后返回结果。是否可以从我发布的内容(或有关我可能做错的一般建议)中查看可能发生的情况?如果有帮助,我可以发布更多代码。

编辑:Wrapper类,以防万一可能是引起问题的原因:
#ifndef WRAPPER_H
#define WRAPPER_H
template< class T>
class Wrapper
{
public:
Wrapper()
{
DataPtr = 0;
}
Wrapper(const T& inner)
{
DataPtr = inner.clone();
}
Wrapper(T* DataPtr_)
{
DataPtr = DataPtr_;
}
~Wrapper()
{
if (DataPtr != 0)
delete DataPtr;
}
Wrapper(const Wrapper<T>& original)
{
if (original.DataPtr != 0)
DataPtr = original.DataPtr->clone();
else
DataPtr = 0;
}
Wrapper& operator=(const Wrapper<T>& original)
{
if (this != &original)
{
T* newPtr = (original.DataPtr != 0) ?
original.DataPtr->clone() : 0;
if (DataPtr != 0)
delete DataPtr;
DataPtr = newPtr;
}
return *this;
}

T& operator*()
{
return *DataPtr;
}
const T& operator*() const
{
return *DataPtr;
}
const T* const operator->() const
{
return DataPtr;
}
T* operator->()
{
return DataPtr;
}
private:
T* DataPtr;
};
#endif

最佳答案

您认为Wrapper类正在创建BSCallFunction对象的多个副本是正确的。

例如:

BSCallFunction ThisBsCall(nominal, S0, r, d, impvol, TTM, Strike);
OneStepBrownianMotionEngine ShortRateSimulation(timeHorizon, zeroDrift, ThisBsCall, RiskFactor::interest_rate);

在上面的行中,创建了一个临时的 Wrapper对象,并将其传递给 OneStepBrownianMotionEngine的构造函数,该构造函数将内部对象克隆并存储指向该对象的指针。然后,将此克隆的对象传递给基类 SimulationEngine,该类使用 Wrapper类的副本构造函数存储其副本。

所以1个临时对象+另一个副本。

其他引擎类 OneStepBrownianMotionEngine也会发生这种情况。

Now my problem is when I look at the 2 BSCallFunction objects (which I expect to be the same ThisBsCall) they have different values for S0 and r, so it seems like at some point I copied the object and changed the value of r or S0 of this copy instead of the original and then returned the result.



它们永远不会相同,因为 Wrapper类旨在克隆传递给它的对象。您可以在堆上创建 ThisBsCall( new BSCallFunction(...))并使用指针。这将确保两个引擎使用相同的 ThisBsCall

但是,正如您所发现的,这将在销毁引擎时引起问题: Wrapper的析构函数试图删除相同的 ThisBsCall对象。双重删除总是会导致崩溃!

您的 Wrapper是什么:
  • 使用指向ThisBsCall的指针,这样就不必复制它了
  • Wrapper对象
  • 的每个共享所有者维护一个引用计数
    当引用计数降至零时,
  • 销毁ThisBsCall对象

  • std::shared_ptr 为您完成所有这一切,它是标准库的一部分。因此,我建议您使用它而不是 Wrapper类。它将需要最少的更改。

    您的代码可以保持不变,只不过您替换了以下实例
    Wrapper<your_class_name>


    std::shared_ptr<your_class_name> 

    例如:
    std::shared_ptr<valuationFunction> ThisBsCall = std::make_shared<BSCallFunction>(nominal, S0, r, d, impvol, TTM, Strike);

    std::shared_ptrstd::unique_ptr一样, smart pointers的美丽之处在于它们将为您处理内存管理。您不必担心手动调用 newdelete。所有这些都在后台为您完成。另外,它们也为您提供异常(exception)安全。如果由于某种原因在分配内存期间引发了异常,则会为您清除内存。由于这些原因以及更多原因,这就是为什么如今建议的做法是使用智能指针而不是自己进行内存管理。

    我不知道您是否在多线程环境中进行编码?尽管存储被管理对象和引用计数器的控制块是线程安全的,但智能指针本身不是。您仍然必须提供自己的线程同步。

    关于c++ - 对象似乎没有通过C++的引用传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61930861/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com