精华内容
下载资源
问答
  • 多线程下静态成员变量初始化几次
    2019-07-02 16:23:29

    1. 如果是编译时和加载时初始化, 是不会存在线程安全这个issue的;  

           因为这两种初始化一定发生在Main函数执行之前, 这个时候尚未进入程序运行空间; 而这些初始化一定是在单线程环境下操作的!  --  都是在执行C Runtime的startup代码中的void mainCRTStartup(void)函数时所在的OS系统加载程序时的主线程空间上发生的!

    2. 如果是运行时初始化, 因为无法保证访问这个静态变量所在的局部函数/全局函数/类成员函数/类静态成员函数  一定只会从某个特定的线程中被访问, 因此, 就一定会存在"线程安全"的issue!

    更多相关内容
  • C++静态成员变量初始化和赋值

    万次阅读 2019-03-07 14:29:57
    使用静态成员变量实现个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。 static成员的所有者是类本身和对象,但是个对象拥有一样的静态成员。从而在定义对象时不能通过构造函数对其进行...

    1.背景

    有这样一套会话机制,CSession为会话对象,CSessionManager为会话管理类,在CSession会话需要销毁时,CSession主动发送消息给CSessionManager销毁session。同时CSession是一个基类,子类通过继承CSession实现不同的session处理。

    实现主要考虑三个方面(创建、处理、销毁):

    1. 通过不同的server创建不同的session会话;
    2. 子类通过CSession提供的虚函数接口实现多态;
    3. 通过消息对象指针发送消息给CSessionManager销毁session;

    问题卡在session的销毁:

    CSessionManager通过消息队列模板类创建消息对象,保存消息对象指针信息,并且有一个线程专门接收该对象发送的消息。那么CSession会话类也需要知道和保存消息对象指针。

    先前有类似情况,消息对象指针是通过构造传参保存下来的。但现在CSession作为一个基类(要被继承),显然通过构造传参是非常不合理的,并且我希望CSession只保存一份消息对象指针(static成员变量),提供唯一 一个发送消息的接口给子类。

    大致代码如下:

    typedef struct
    {
    	int connfd;
    	int keepfd;		/*是否保留fd:1-是,其他-否*/
    }SocketSessionExp;
    
    //session会话基类(HttpSession、RtspSession继承该类)
    class CSession
    {
    	friend class CSessionManager;
    	public:
    		CSession();
    		virtual ~CSession();
    	protected:
    		static void sendMessage(SocketSessionExp &expMessage);//希望CSession对象和子类能通过这个唯一接口发送消息给CSessionManager销毁该CSession会话
    	private:
    		static TMessageQue<SocketSessionExp> *m_exception_msq;//TMessageQue为消息队列模板类
    }
    
    //会话管理类
    class CSessionManager
    {
    public:
    	static CSessionManager* instance();		//单健类
    private:
    	CSessionManager();
    	{
    		m_exception_msq = new TMessageQue<SocketSessionExp>();
    		CSession::m_exception_msq=m_exception_msq;
    	}
    	~CSessionManager();//不是重点未给出
    private:
    	static TMessageQue<SocketSessionExp> *m_exception_msq;//在构造函数中new一个类对象
    	std::map<int,CSession*>			m_sessionMap;
    }
    
    

    该模块编译时没报错,链接时报错提示:

    undefined reference to `Network::CSession::m_exception_msq'
    

    2.试错

    CSessionManager是CSession的友元类,可直接访问CSession的私有成员和保护成员。也尝试通过函数、局部CSession等方式来完成m_exception_msq的赋值,均报错。

    3.分析与百度

    class CSession
    {
    	friend class CSessionManager;
    	public:
    		CSession();
    		virtual ~CSession();
    	private:
    		static TMessageQue<SocketSessionExp> *m_exception_msq;//TMessageQue为消息队列模板类
    }
    

    分析-有用信息:

    1. 在如上代码中,m_exception_msq只是声明,并没有定义和初始化。
    2. “undefined reference to”是未定义……;
    3. 项目中有地方使用静态变量的地方都在.cpp文件上方进行了初始化(实际是定义–>初始化)。

    分析推测:应该是m_exception_msq未定义。

    在.cpp文件中添加如下代码:

    //xxx.cpp
    TMessageQue<SocketSessionExp>* CSession::m_exception_msq=NULL;
    

    编译成功、链接成功、通过打印信息也看到CSession::m_exception_msq在CSessionManager构造中完成了赋值,问题解决了。

    这里一方面是对static成员变量的理解不到位,另一方面是分析的时候没有抓住有效信息浪费了不少时间。(“undefined reference to”)

    4.C++静态成员变量

    C++的变量的类型大致有普通成员变量、静态成员变量、成员常量这三种,还有一种组合的静态成员常量。

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

    static成员的所有者是类本身和对象,但是多个对象拥有一样的静态成员。从而在定义对象时不能通过构造函数对其进行初始化; 静态成员不能在类定义里边初始化,只能在class body外初始化; 静态变量依旧符合public、private、protect特性; 静态成员函数没有this指针,它不能返回非静态成员,因为除了对象会调用它外,类本身也可以调用 。

    C++静态成员变量:

    1. 必须在外部定义和赋值;
      • 不能在 main() 函数中定义
      • 不能在类的构造函数中定义
    2. 必须要定义静态变量,否则该变量没有内存空间(类中只是申明) ;
    3. 类本身可以直接调用静态变量
    4. 静态变量依旧符合public、private、protect特性

    C++成员变量声明、初始化、赋值说明列表:

    数据成员类型normalconststaticstatic const
    类内直接初始化(在声明时就赋值)×
    先声明再通过初始化列表赋初值××
    先声明再在构造函数体里赋初值×××
    先声明再在类外赋初值××

    5.C++静态成员方法

    1、静态方法可以被类直接调用,但是同静态变量一样符合public、private、protect特性

    2、静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。

    3、静态成员函数不可以同时声明为 virtual或后缀const 函数。因为virtual就是用来区分是哪个对象调用了他,与静态方法矛盾。而后缀const是用来修饰this指针的,静态变量中不包含this指针。

    参考资料:
    https://blog.csdn.net/nwd0729/article/details/47067549
    https://blog.csdn.net/buknow/article/details/80275191

    展开全文
  • 对编译器来说,静态成员变量初始化顺序和析构顺序是一个未定义的行为 #include <string> #include <iostream> using namespace std; class Base{ public: static int b; static int a; }; int ...

    对编译器来说,静态成员变量的初始化顺序和析构顺序是一个未定义的行为

    #include <string>
    #include <iostream>
    using namespace std;
    class Base{
    public:
        static int b;
        static int a;
        
    };
    int Base::b = 2;
    int Base::a = b + 1;
    
    
    
    
     
    int main()
    {
        Base base;
        cout <<"Base::a="<< Base::a << endl;
        cout <<"Base::b="<< Base::b << endl;
     
        return 0;
    }
    
    
    

    请添加图片描述

    6 7 18 19 行怎么修改值都一样可见静态类型成员变量的初始化顺序和编译器和有关
    如下文所说:https://wenku.baidu.com/view/60a101842b4ac850ad02de80d4d8d15abe2300da.html
    理解在⼀个应⽤程序内部,静态变量的构造/析构顺序。其中,对于全局静态变量,视编译器的实现⽽定(⼀种⽅式是根据字
    母顺序来决定);对于有依赖关系的,那么视依赖关系⽽定。⽽对于局部静态变量来说,问题就开始复杂了。这也正是本⽂论述的重点。
    ⾸先,要理解编译器是如何实现局部静态变量的语法特性的。从语法上来看,局部静态变量与全局静态变量最⼤的不同在于构造时机——当
    且仅当程序执⾏路径⾸次达到局部静态变量的定义处才出发构造。注意是⾸次。印象中编译器是通过添加⼀个标识变量(当然这个变量⼀定
    是全局静态的)来实现的(即每次程序执⾏到时,⾸先检查这个标志变量),如此来确保调⽤时构造且只构造⼀次的特性。那么反过来看局
    部静态变量的析构,编译器会维护⼀个析构函数的函数指针栈,⼀旦构造完成,就会把相应的析构函数指针放到这个栈中。当程序结束后,
    由编译器⽣成的doexit函数会逐个调⽤这些析构函数,完成进程结束前的扫尾⼯作。基于此,很显然,对于分布在程序各处的静态局部变
    量,其构造顺序取决于它们在程序的实际执⾏路径上的先后顺序,⽽析构顺序则正好与之相反。
    很简单,不是么?可为什么说是隐藏的坑呢,问题在于:

    ⼀⽅⾯是因为程序的实际执⾏路径有多个决定因素(例如基于消息驱动模型的程序和多线程程序),有时是不可预知的; 另⼀⽅⾯是因为局部静态变量分布在程序代码各处,彼此直接没有明显的关联,很容易让开发者忽略它们之间的这种关系(这是最坑的地 ⽅)。

    既然提出问题,那么就讨论应对之道:
    (1)最简单的,避免使⽤局部静态变量,将变量的声明周期控制在开发者⼿中;
    (2)如果确有需要,那么尽量确保局部静态变量之间构造和析构是彼此独⽴互不相关的,换句话说,它们可以以任意的顺序被构造和析
    构;
    设计模式里的单例模式就有静态变量互相引用从而系统奔溃。
    测试程序

    #include <string>
    #include <iostream>
    using namespace std;
    class Log
    {
    public:
        static Log* GetInstance()
        {
            static Log oLog;
            return &oLog;
        }
     
        void Output(string strLog)
        {
            cout<<strLog<<(*m_pInt)<<endl;
        }
    private:
        Log():m_pInt(new int(3))
        {
        }
        ~Log()
        {cout<<"~Log"<<endl;
            delete m_pInt;
            m_pInt = NULL;
        }
        int* m_pInt;
    };
     
    class Context
    {
    public:
        static Context* GetInstance()
        {
            static Context oContext;
            return &oContext;
        }
        ~Context()
        {
            Log::GetInstance()->Output(__FUNCTION__);
        }
     
        void fun()
        {
            Log::GetInstance()->Output(__FUNCTION__);
        }
    private:
        Context(){}
        Context(const Context& context);
    };
     
    int main(int argc, char* argv[])
    {
        Context::GetInstance()->fun();
        return 0;
    }
    
    
    

    参考博客:https://www.freesion.com/article/7937607333/

    展开全文
  • C++当中常常需要一个全局唯一的对象... 既然全局变量是可能有害的,那么,我们我们把它隐藏一下,放到某个类当中去,作为类的静态数据成员。这看上去不错,我也这么认为。当我们只是简单的需要一个全局对象时,这很
    C++当中常常需要一个全局唯一的对象实例,这时候,我们就会想到单件模式。如何实现这一模式?全局变量当然是一个简单可行的方法,然而,这太丑陋。嗯,其实,丑陋倒也罢了,最严重的是它将引诱程序员滥用全局变量,这将导致维护的灾难。
      
      既然全局变量是可能有害的,那么,我们我们把它隐藏一下,放到某个类当中去,作为类的静态数据成员。这看上去不错,我也这么认为。当我们只是简单的需要一个全局对象时,这很好,而且足够简单。不过,天空中尚有一朵小小的乌云,让我们来看一看它是什么。
      
      静态成员变量的初始化,和全局对象一样,实际上实在main函数进入后,我们写下的一行代码之前被执行的。而且,我们知道那个著名的初始化顺序是不可靠的问题(跨编译单元)。当我的全局对象是一个复杂对象――这很常见,比如一个环境管理器――它甚至还需要复杂的装配过程,我们需要考虑:构建这个单件的时候,其对象都准备好了吗?如果我们不能确定,那么一个常见的措施是延迟单件对象的构造――把它延迟到全局对象初始化结束以后怎么样?这好像很容易实现:
      
      SomeClass * SomeClass ::instance(){
      static SomeClass inst;
      return &inst;
      }
      
      不错吧?它不但可以延迟到全局对象初始化之后,甚至可以延迟到有人需要它的时候,才被构造出来,随需应变,呵呵,是不是很帅?嗯,还有一点小问题,不仅存在对象初始
    展开全文
  • C++11中静态局部变量初始化线程安全性

    千次阅读 多人点赞 2019-04-07 15:03:31
    大家都知道,在C++11标准中,要求局部静态变量初始化具有线程安全性,所以我们可以很容易实现一个线程安全的单例类: class Foo { public: static Foo *getInstance() { static Foo s_instance; return &...
  • 静态变量的内存分配和初始化 对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。由于内置变量无须资源释放操作,仅需要回收...
  • C#中静态变量初始化

    千次阅读 2016-06-10 12:05:15
    类的静态字段变量初始值设定项对应于一个赋值序列,这些赋值按照它们在相关的类声明中出现的文本顺序执行。 如果类中存在静态构造函数则静态字段初始值设定项的执行在该静态构造函数即将执行前发生。 否则,静态字段...
  • 1、成员变量成员变量有默认初始值,而方法内的局部变量却没有初始值。...一、类的成员变量初始化 ---在JVM类加载阶段完成类的成员变量又分为静态成员变量和非静态成员变量静态成员变量静态成员变量会被初...
  • 静态变量的内存分配和初始化对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。由于内置变量无须资源释放操作,仅需要回收...
  • Java多线程中static变量的使用

    千次阅读 2022-02-17 21:44:22
    Java多线程中static变量的使用 线程,是我们项目中绕不过的重点领域。提到线程,就常会听到线程安全的术语。那什么是线程安全呢?通俗点说,就是线程访问时不产生资源冲突。其实,这是一个有点难以
  • 静态变量的内存分配和初始化 c 对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。由于内置变量无须资源释放操作,仅需要...
  • Java Static 变量初始化

    2021-01-01 11:02:31
    目录Java Static 变量初始化直接赋值static块初始化实例方法初始化解决方案 Java Static 变量初始化 static变量初始化方式 ...直接赋值是较为常见的静态变量初始化方式,用于常量。 static块初始化 static int coun
  • ThreadLocal是JDK提供的,支持线程本地变量。也就是说,如果我们创建了一个ThreadLocal变量,则...如果线程同时对这个变量进行读写操作时,实际上操作的是线程自己本地内存中的变量,从而避免了线程安全的问题。
  • 我已经阅读了很,但是还没有找到确切的答案。我有一堂课,看起来像这样:public class Foo() {private static final HashMap sharedData;private final HashMap myRefOfInnerHashMap;static {// time-consuming ...
  • 静态变量即静态成员变量。只要有修改变量值的操作,无论是在单例或者非单例都是线程不安全的;而如果线程只是读取变量的值,而不会改变变量的值,这种情况则是线程是安全的。 产生线程安全问题的原因:静态变量即...
  • java中static变量只能初始化

    万次阅读 2015-04-05 11:19:39
    C语言中静态变量只能被初始化一,下次即使程序执行到初始化语句也会忽略,在java中也是一样,只是java在链接阶段对变量进行初始话的,而且即使即使后续在类的实例初始化阶段也不会再执行连接阶段的静态变量初始化...
  • Java中成员变量、局部变量、全局变量、静态变量存在位置及初始化 因为线程是共享进程的资源的,所以栈是私有的,堆是公有的。 (1)程序内存布局场景,堆与栈表示两种内存管理方式; (2)数据结构场景,堆与栈...
  • 什么时候初始化 根据 C++ 标准,全局变量初始化要在 main 函数执行前完成,常识无疑,但是这个说法...答案是既有编译时,也可能会有运行时(seriously), 从语言的层面来说,全局变量初始化可以划分为以下两
  • C++中单实例模式的一个简单的写法是:将对象定义为一个函数的局部静态变量,然后返回对象的引用,这样在函数首次调用时完成静态对象的初始化,但这一做法在C++11前并不是线程安全的,而C++11已经可以保证其线程安全...
  • Java-静态成员变量值到底能不能变?

    万次阅读 多人点赞 2018-01-23 19:10:53
    Java-静态成员变量值到底能不能变??
  • 函数如下,在C++中声明静态成员变量的时候,在类中只是进行了声明,并没有实际的申请出指针的内存,真正的内存是定义初始化的时候才会进行内存的申请,因此,又因为static类型的变量都是随着类的,因此不能随着对象...
  • 这两种变量引起线程安全问题的原因和区别如下:1、静态变量静态变量即静态成员变量。只要有修改变量值的操作,无论是在单例或者非单例都是线程不安全的;而如果线程只是读取变量的值,而不会改变变量的值,这种情况...
  • 本文主要介绍C++回调函数中调用类中的非静态成员变量或非静态成员函数 回调函数中调用类中的非静态成员变量或非静态成员函数 【问题】如何在类中封装回调函数? a.回调函数只能是全局的或是静态的。 b.全局函数会...
  • 类内有成员变量,而成员变量初始化顺序是定义成员变量时决定的,而不是构造函数里赋值的顺序决定的,记得网上有类似的笔试题。 class Type { public: Type() :b(2), a(1){ } private: int a; int...
  • 全局变量在整个源文件的作用域都是有效的,只需要在一个源文件中定义全局变量,在其他不包含全局变量定义的源文件中用extern关键字再次声明这个全局变量即可。 也可以在一个源文件中定义这个全局变量,在头文件中用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 114,958
精华内容 45,983
热门标签
关键字:

多线程下静态成员变量初始化几次