讲讲c++ Session 3:静态成员(变量,函数)

本文详细介绍了C++中静态成员的概念及其应用场景。静态成员属于整个类而非特定对象,能够实现多个对象间的数据共享,同时保证数据的安全性和节省内存。文章通过具体示例展示了如何定义和访问静态成员,并强调了在静态成员函数中的一些限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

静态成员:在说明前面加了static关键字的成员。 在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。
设立原因:使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

程序实例:

class CRectangle
{
private:
int w, h;
static int nTotalArea; //静态成员变量
static int nTotalNumber;
public:
CRectangle(int w_,int h_);
~CRectangle();
static void PrintTotal(); //静态成员函数
};
访问静态成员:
1) 类名::成员名
CRectangle::PrintTotal();
2) 对象名.成员名
CRectangle r; r.PrintTotal();
3) 指针->成员名
CRectangle * p = &r; p->PrintTotal();
4) 引用.成员名
CRectangle & ref = r; int n = ref.nTotalNumber;


注意Tips:
在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。
例如:

void CRectangle::PrintTotal()
{
cout << w << "," << nTotalNumber << "," << nTotalArea << endl; //wrong
}
CRetangle::PrintTotal(); //解释不通,w 到底是属于那个对象的?
CRectangle::CRectangle(int w_,int h_)
{
w = w_;
h = h_;
nTotalNumber ++;
nTotalArea += w * h;
}
CRectangle::~CRectangle()
{
nTotalNumber --;
nTotalArea -= w * h;
}
void CRectangle::PrintTotal()
{
cout << nTotalNumber << "," << nTotalArea << endl;
}


错误原因:
在使用CRectangle类时,有时会调用复制构造函数生成临时的隐藏的CRectangle对象,调用一个以CRectangle类对象作为参数的函数时和调用一个以CRectangle类对象作为返回值的函数时,临时对象在消亡时会调用析构函数,减少nTotalNumber 和nTotalArea的值,可是这些临时对象在生成时却没有增加nTotalNumber 和 nTotalArea的值。


<think>好的,我现在需要解决用户在C++中定义全局Ort::Env变量时出现的运行错误问题。根据用户提供的引用内容,我需要先理解问题可能的原因以及如何正确初始化和使用Ort::Env。 首先,用户提到在定义全局Ort::Env变量时遇到运行错误。全局变量的初始化顺序在C++中是不确定的,这可能导致在Ort::Env初始化之前就尝试使用它,从而引发问题。例如,其他全局对象可能在构造函数中使用了Ort::Env,而此时Ort::Env尚未正确初始化,导致异常。 接下来,我需要参考用户提供的引用内容。引用[3]指出Windows系统可能存在同名DLL冲突,需要将ORT库的DLL复制到exe目录下。这可能与动态链接库的加载顺序有关,但用户的问题是关于全局变量的,所以可能与此无关,不过还是需要注意环境配置是否正确。 引用[4]和[5]提到了Ort::Exception异常,可能与张量创建或输入名称获取有关,但用户的问题更侧重于全局变量的初始化。因此,重点应放在Ort::Env的初始化和生命周期管理上。 解决方案方面,可能的步骤如下: 1. 避免使用全局Ort::Env变量,改用单例模式或静态局部变量,确保在使用前正确初始化。 2. 检查是否所有依赖的DLL文件(如onnxruntime.dll)已正确部署,避免因DLL冲突导致初始化失败。 3. 确保Ort::Env的初始化参数正确,例如日志级别和线程池设置。 4. 使用智能指针或包装类来管理Ort::Env的生命周期,确保其在整个应用程序中有效存在,并在程序结束时正确释放。 此外,用户提供的引用[1]和[2]涉及头文件包含和环境配置,可能影响项目的编译和链接,但更多是与代码结构相关的问题,需要确认项目配置是否正确。 最后,需要验证解决方案是否有效,例如将Ort::Env作为静态局部变量,在首次使用时初始化,避免全局变量的初始化顺序问题。同时,确保在程序退出前不提前释放资源,防止析构顺序问题。</think>在C++中使用ONNX Runtime的全局变量$Ort::Env$时,若出现运行错误,通常与初始化顺序、生命周期管理和环境配置相关。以下是分步解决方案: --- ### 1. **避免全局变量的初始化顺序问题** **现象**:全局变量可能在其他依赖它的全局对象初始化前被使用,导致$Ort::Exception$异常[^5]。 **解决方案**:改用静态局部变量或单例模式,确保$Ort::Env$在使用时已正确初始化。 ```cpp // 使用静态局部变量 Ort::Env& GetOrtEnv() { static Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "Default"); return env; } // 在代码中调用 void MyFunction() { Ort::Env& env = GetOrtEnv(); // 使用env进行后续操作 } ``` --- ### 2. **正确管理生命周期** **现象**:全局变量$Ort::Env$可能在程序退出时被提前销毁,导致析构顺序问题[^3]。 **解决方案**:使用智能指针封装$Ort::Env$,确保其生命周期覆盖整个程序运行期。 ```cpp #include <memory> std::shared_ptr<Ort::Env> GetGlobalOrtEnv() { static auto env = std::make_shared<Ort::Env>(ORT_LOGGING_LEVEL_WARNING, "Global"); return env; } ``` --- ### 3. **检查DLL依赖和路径配置** **现象**:Windows可能优先加载系统目录下的同名DLL(如$onnxruntime.dll$),导致版本冲突。 **解决步骤**: 1. 将ONNX Runtime库目录下的以下文件复制到生成的`.exe`同级目录: - `onnxruntime.dll` - `onnxruntime_providers_shared.dll` - `onnxruntime_providers_cuda.dll`(若使用CUDA) 2. 确保项目属性中`附加库目录`正确指向ONNX Runtime的`lib`目录。 --- ### 4. **验证初始化参数** **现象**:错误的初始化参数(如日志级别、线程池配置)可能导致异常[^4]。 **正确初始化示例**: ```cpp Ort::Env env( ORT_LOGGING_LEVEL_WARNING, // 日志级别 "MyApp", // 日志标签 Ort::ThreadingOptions() // 线程池配置(默认即可) ); ``` --- ### 5. **完整代码示例** ```cpp #include <onnxruntime_cxx_api.h> // 必须包含此头文件[^1] class OrtWrapper { public: static Ort::Env& GetEnv() { static Ort::Env instance(ORT_LOGGING_LEVEL_WARNING, "GlobalEnv"); return instance; } }; int main() { // 使用全局Env Ort::Env& env = OrtWrapper::GetEnv(); // 创建会话 Ort::SessionOptions session_options; Ort::Session session(env, "model.onnx", session_options); return 0; } ``` --- ### 关键问题总结 | 问题类型 | 解决方案 | 引用来源 | |-------------------|-----------------------------|-----------| | 初始化顺序 | 改用静态局部变量或单例模式 | | | DLL冲突 | 复制正确DLL到exe目录 | | | 生命周期管理 | 使用智能指针封装Env对象 | [^4] |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值