C++

从tensorflow注册OP想到的--C++全局变量初始化时期

Posted by XP on April 1, 2019

从tensorflow注册新OP想到的

1,一个小引子

题目如下: 在不改变main函数的情况下,在“hello world!”之前打印一句”12345”

int main()
{
    cout << "hello world!" << endl;
    return 0;
}

借助C++全局变量在程序开始之后,main函数之前就会初始化的性质,我们可以定义一个 全局变量,并在他的构造函数中打印”12345”

class A
{
pubcli:
    A(){
        cout << "12345" << endl;
    }
};

A a;

//main 函数

如果还要调用其他函数,也可以。比如下面就在A的构造函数里面new了一个B

#include <iostream>  

using namespace std;  

class B{
public:
    B(){ cout << "this is B" << endl; }
};

class A{
public:
    A(){
        _b = new B();
        cout << "12345" << endl;
    }

private:
    B *_b;
};

A a;


int main()
{
    cout << "hello world!" << endl;
    return 0;
}

打印结果:
this is B
12345
hello world!

2,注册OP代码分析

下面代码片段和tensorflow注册OP的代码类似:


#include <iostream>  

#include <memory>  

using namespace std;  

class B{
public:
    B(){ cout << "this is B" << endl; }
    virtual ~B(){}
};


class Regizter
{
public:
    Regizter(shared_ptr<B> (*)()){ cout << "this is Regizter with function" << endl;}
    Regizter(){ cout << "this is Regizter without param" << endl;}
};


#define OP_CREATER(name, clazz)                         \  

    shared_ptr<B> create##name##op()                    \   
    {                                                   \   
        shared_ptr<clazz> ptr = nullptr;                \   
        ptr = make_shared<clazz>();                     \   
        return shared_ptr<B>(ptr);                      \   
    }                                                   \   
    Regizter g##name##creater(create##name##op)   
    //Regizter g##name##creater()   

class bn : public B
{
public:
    bn(){ cout << "bn" <<endl;}
};


OP_CREATER(BN, bn);

int main()
{
    cout << "this is main" << endl;
    return 0;
}

上述代码有以下几个理解点:

  • ## : 在C++中用于拼接符号,详细信息参考这里
  • OP_CREATER宏 使用该宏将定义一个函数createXXop, 此处的shared_ptr应用于工厂函数,请参看《Effective Modern C++》— Use std::unique_ptr for exclusive-ownership resource management

  • Regizter g##name##creater(create##name##op) 以OP_CREATER(BN, bn)为例,这一句宏替换后的形式为: Regizter gBNcreater(createBNop); 可以看出就是定义了一个Regizter类型的全局变量gBNcreater,调用带参的构造函数,所以可以知道上述代码打印结果是:
    this is Regizter with function   
    this is main
    

一个小错误
如果想使用无参构造函数怎么办?可以看到上面代码注释掉了 Regizter g##name##creater(),然而并没有打印”this is Regizter without param”,这是因为宏展开后,这句只是一个函数声明,Regizter gBNcreater(),而不是一个变量定义,因此把()去掉,就成为了变量定义.