在C中有效传递字符串文字

Efficient passing of string literals in C++

在编写用于包装Lua的代码时,我遇到了传递字符串文字的需求,并开始想知道哪种方式最有效。

我可以在两个功能之间进行选择:

  • void lua_pushstring (lua_State* L, const char* str);
  • void lua_pushlstring(lua_State* L, const char* str, size_t len);
  • 当然,第一个函数在内部使用strlen(),因此第二个函数更快。

    现在,如果在编译时就知道了,我想避免计算字符串长度,如此处和此处所示:

    1
    2
    3
    4
    5
    6
    // Overload 1
    template <size_t N>
    inline void pushstring(lua_State* L, const char (&str) [N])
    {
        lua_pushlstring(L, str, N-1);
    }

    使用字符串文字调用此函数时效果很好:pushstring(L,"test");当然,使用const char*调用时不会编译,例如在.cpp文件中的较长函数中:<铅>

    1
    2
    3
    4
    5
    6
    7
    // this is in a .cpp file
    void long_function(lua_State* L, const char* str)
    {
        // do lots of stuff
        pushstring(L, str);  // compile error
        // do more stuff
    }

    现在,如果我添加

    1
    2
    3
    4
    5
    // Overload 2
    inline void pushstring(lua_State* L, const char* str)
    {
        lua_pushstring(L, str);
    }

    由于某种原因(C重载解析很棘手)优于Overload 1,因此从未调用过。

    有解决这个问题的聪明方法吗?


    如果同时声明了两个和第二个,则转发到第一个:

    1
    2
    3
    4
    void lua_pushlstring(lua_State* L, const char* str, size_t len);

    inline void lua_pushstring (lua_State* L, const char* str)
    { lua_pushlstring(L, str, strlen(str)); }

    然后,当您使用文字(例如)调用第二个函数时,一个体面的编译器将优化strlen调用。它将内联

    1
    lua_pushstring(L,"hello");

    ,并且因为文字上的strlen可以优化为常量,所以它将用以下调用代替:

    1
    lua_pushlstring(L,"hello", 5);

    这为您提供了调用两个参数的形式的简单语法,而无需支付字面量的strlen

    已知长度时可以通过:

    1
    lua_pushlstring(L, s.c_str(), s.length());

    或者这也可以,但是不需要调用strlen

    1
    lua_pushstring(L, s.c_str());


    我将提供两种选择:

    1
    2
    3
    4
    void f( const char*, int );
    template <int N> void f( const char (&str)[N] ) {
       f( str, N-1 );
    }

    (或更确切地说是std::size_t),现在具有字符串文字的用户可以调用第二个,而第二个将在内部调度到第一个。没有文字而是const char*的用户负责提供正确的大小。


    要进一步详细说明您的模板版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <iostream>

    template <typename T>
    inline void pushstring(T str);

    template <int N>
    inline void pushstring(const char (&str) [N])
    {
       std::cout << N << std::endl;
    }

    template <>
    inline void pushstring(const char *str)
    {
       std::cout << str << std::endl;
    }

    在此处查看测试运行:
    参数错误->链接器错误:http://ideone.com/vZbj6
    Rigt参数->运行良好:):http://ideone.com/iJBAo