代码之家  ›  专栏  ›  技术社区  ›  c00000fd

C+VS C++静态数组中静态常数列表初始化的效率

  •  2
  • c00000fd  · 技术社区  · 7 年前

    我事先道歉。我的域名主要是C(和C++)。我想用C语言写一些类似的东西。让我用代码解释一下。

    在C++中,我可以使用大型静态数组,这些数组在编译时被处理,并存储在PE文件的只读部分中。例如:

    typedef struct _MY_ASSOC{
        const char* name;
        unsigned int value;
    }MY_ASSOC, *LPMY_ASSOC;
    
    bool GetValueForName(const char* pName, unsigned int* pnOutValue = nullptr)
    {
        bool bResult = false;
        unsigned int nValue = 0;
    
        static const MY_ASSOC all_assoc[] = {
            {"name1", 123},
            {"name2", 213},
            {"name3", 1433},
            //... more to follow
            {"nameN", 12837},
        };
    
        for(size_t i = 0; i < _countof(all_assoc); i++)
        {
            if(strcmp(all_assoc[i].name, pName) == 0)
            {
                nValue = all_assoc[i].value;
                bResult = true;
                break;
            }
        }
    
        if(pnOutValue)
            *pnOutValue = nValue;
    
        return bResult;
    }
    

    在上面的示例中,初始化 static const MY_ASSOC all_assoc 从不在运行时调用。它完全在编译期间处理。

    现在,如果我用C语言写类似的东西:

        public struct NameValue
        {
            public string name;
            public uint value;
        }
    
        private static readonly NameValue[] g_arrNV_Assoc = new NameValue[] {
            new NameValue() { name = "name1", value = 123 },
            new NameValue() { name = "name2", value = 213 },
            new NameValue() { name = "name3", value = 1433 },
            // ... more to follow
            new NameValue() { name = "nameN", value = 12837 },
        };
    
        public static bool GetValueForName(string name, out uint nOutValue)
        {
            foreach (NameValue nv in g_arrNV_Assoc)
            {
                if (name == nv.name)
                {
                    nOutValue = nv.value;
                    return true;
                }
            }
    
            nOutValue = 0;
            return false;
        }
    

    线 private static readonly NameValue[] g_arrNV_Assoc 必须在宿主类初始化期间调用一次,并且对该数组中的每个元素都调用一次!

    所以我的问题——我能不能优化它,使存储在 g_arrNV_Assoc 数组存储在pe部分,在运行时不初始化?

    我希望我能用我的术语对.NET人员有所了解。

    1 回复  |  直到 7 年前
        1
  •  1
  •   TheGeneral    7 年前

    实际上,这个术语已经足够了,大型静态数组就可以了。

    你真的无能为力,使它更有效的开箱即用。

    它最初将加载一次(在不同的时间,取决于.NET的版本以及是否有静态构造函数)。但是,它将在您调用它之前加载。

    即使您只使用预先确定的大小创建了一个空元素,clr仍然会将每个元素初始化为默认值,那么您将不得不以某种方式缓冲对数据的复制,而这反过来又必须从文件中加载。

    但问题是

    • 与在C中所做的相比,加载结构的默认静态数组实际需要多少开销
    • 在应用程序的生命周期中,当它被加载时,它是否重要?

    如果这太过分了(我已经假设你已经决定了),那么在盒子之外还有什么其他的选择呢?

    您可以预先分配一块非托管内存,然后从某处读取和复制字节,然后使用指针进行Inturn访问。

    您也可以在标准的dll中创建这个,就像其他未管理的dll一样。不过,我真的不确定您是否会在这里得到很多免费午餐,因为有很多开销来整理这些类型的调用来加载您的DLL。

    如果你的问题只是学术性的,那么这些是你唯一的选择。但是,如果这实际上是一个性能问题,那么您需要尝试将其作为微优化的基准,并尝试找出什么适合您。

    不管怎样,我并不是说什么都知道,也许其他人有更好的想法或更多的信息。祝你好运