在C ++中可扩展的自动类注册 [英] Scalable automatic class registration in C++

查看:93
本文介绍了在C ++中可扩展的自动类注册的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中自动类注册是一个常见的任务,这里的StackOverflow常见问题:

Automatic class registration in C++ is a common task, and a commonly asked question here on StackOverflow:

Register an object creator in object factory

现在可以在列表中注册我的课程

使用宏自动注册对象创建者函数< a>

automatic registration of object creator function with a macro

c ++自动工厂注册派生类型

基本目标是自动注册一些注册表或工厂,以便它以后可以对每个类做一些工作。

The basic objective is to register classes automatically with some registry or factory so that it can do some work with each class later.

这是一个成熟的技术,由像(例如)Google Test( http://code.google.com/p/googletest ),它会自动注册Test类的子类,以便每个测试可以自动实例化并在测试执行期间运行。

This is a well-established technique, used by libraries like (for example) Google Test (http://code.google.com/p/googletest), which automatically registers subclasses of the Test class so that each test can be instantiated automatically and run during test execution.

注册可以通过实例化一个静态注册器类来完成,该注册器类的构造函数执行注册,或者巧妙地使用CRTP并将注册代码放在基类构造函数中,无论你喜欢什么(上面的链接提供了几种不同的可能的技术)。

Registration can be accomplished by instantiating a static Registrar class whose constructor does the registration, or by clever use of the CRTP and putting the registration code in the base class constructor, or whatever you like (the links above offer several different possible techniques).

然而,当我实现任何这些技术,我发现他们规模非常差。如果我在Google测试中有10,000个TEST宏调用,编译和链接研究停止(MSVC 2010)和二进制大小爆炸。如果我实现这个另一种方式,使用10,000个子类与静态注册器,我看到相同的行为。

However, when I implement any of these techniques I find they scale very poorly. If I have 10,000 TEST macro invocations in Google Test, compilation and linking grind to a halt (MSVC 2010) and binary size explodes. If I implement this another way, using 10,000 subclasses with static registrars, I see the same behavior.

例如,考虑简化的例子:

For instance, consider the simplified example:

#include <iostream>
#include <string>

class Base {

    public:

        Base( const std::string& Name_ ) : Name( Name_ ) { ; }
       ~Base() { ; }

        virtual std::string GetName() const { return Name; }
        virtual void DoSomething() = 0;

    private:

        std::string Name;

};

class Registry {

    public:

        static Registry& GetInstance() {
            static Registry* Instance = new Registry();
            return *Instance;
        }

        void Register( const Base* b ) {
            std::cout << "Registered class " << b->GetName() << std::endl;
        }

    private:

        Registry()  { ; }
       ~Registry()  { ; }

};

class Registrar {

    public:

        Registrar( const Base* b ) {
            Registry::GetInstance().Register( b );
        }

       ~Registrar() { }

};


#define  REGISTER( CLASS )                                          \
    class CLASS : public Base {                                     \
        public:                                                     \
            CLASS( const std::string& Name ) : Base( Name ) { ; }   \
            virtual void DoSomething();                             \
        private:                                                    \
            static Registrar m_Registrar;                           \
    };                                                              \
    Registrar CLASS::m_Registrar( new CLASS( #CLASS ) );            \
    void CLASS::DoSomething()


int main( int argc, char** argv )
{
    return 0;
}


REGISTER( Class1 )
{
    std::cout << "Doing something in Class1" << std::endl;
}

REGISTER( Class2 )
{
    std::cout << "Doing something in Class2" << std::endl;
}

[...]

的10000个自动生成的REGISTER调用。

with a total of 10000 autogenerated REGISTER calls.

有什么根本原因,这将无法扩展好吗?编译器只会阻塞10000个类吗?在MSVC 2010下编译上述需要几乎两分钟在一个相当快的机器,并产生一个二进制超过5 MB的大小。如果我与Google Test类似,我看到的结果相同。

Is there a fundamental reason why this won't scale well? Will the compiler just choke on 10000 classes? Under MSVC 2010 compilation of the above takes almost two minutes on a fairly fast machine and produces a binary over 5 MB in size. If I do similar with Google Test I see the same result.

推荐答案

在C ++中编写Java代码很少有效。所有这些堆分配可能是杀死性能(如在Java中,但Java启动是如此之慢,没有人会注意到)。使用静态对象,不要在每个生成的类中放置注册器对象;这只是浪费时间和空间。

Writing Java code in C++ rarely works well. All those heap allocations are probably what's killing performance (as they would in Java, but Java startup is so slow that nobody would notice). Use static objects, and don't put a Registrar object into each generated class; that's just a waste of time and space.

这篇关于在C ++中可扩展的自动类注册的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆