当前位置: 首页 > 知识库问答 >
问题:

数组的具体化内联函数

韦鸣
2023-03-14
inline fun <reified E> getArray(key: String, defValue: Array<E>): Array<E>? {
    return when(defValue) {
        is Array<Int> -> // ...
        is Array<String?> -> // ...
        else // ...
    }
}
fun intArray(size: Int): Array<Int> = Array(size) {i -> 0}
fun stringArray(size: Int): Array<String?> = Array(size) {i -> null}

val strings: Array<Int> = getArray(KEY_INTS, intArray(0))
val strings: Array<String> = getArray(KEY_STRINGS, stringArray(0))

共有1个答案

云俊名
2023-03-14

显式回答问题-您可以通过检查E类来使用它:

inline fun <reified E: Any> getArrayInline(key: String, defValue: Array<E>): Array<E>? {
    return when(E::class) {
        Int::class -> arrayOf(1, 2, 3)
        String::class -> arrayOf("a", "b", "c")
        else -> throw IllegalArgumentException("Invalid class: ${E::class.qualifiedName}")
    } as Array<E>
}

但我不愿意使用它,因为:

  1. 它不是类型安全的-您必须对结果执行不安全的强制转换,并且可以对任何数组类型调用它,即使它不包括在whencases
  2. 它是内联的-所以每当您使用该方法时,整个代码块都会被复制到字节码中(见下文)
  3. 类型检查是在运行时进行的,因此会影响性能
fun testArrayInline(){
    val test = getArrayInline("key", emptyArray<Int>())
    val test2 = getArrayInline("key2", emptyArray<String>())
}
public static final void testArrayInline() {
  String var1 = "key";
  Object[] defValue$iv = new Integer[0];
  KClass var3 = Reflection.getOrCreateKotlinClass(Integer.class);
  Object var10000;
  if (Intrinsics.areEqual(var3, Reflection.getOrCreateKotlinClass(Integer.TYPE))) {
     var10000 = new Integer[]{1, 2, 3};
  } else {
     if (!Intrinsics.areEqual(var3, Reflection.getOrCreateKotlinClass(String.class))) {
        throw (Throwable)(new IllegalArgumentException("Invalid class: " + Reflection.getOrCreateKotlinClass(Integer.class).getQualifiedName()));
     }

     var10000 = new String[]{"a", "b", "c"};
  }

  Integer[] test = (Integer[])((Object[])var10000);
  String var7 = "key2";
  Object[] defValue$iv = new String[0];
  KClass var4 = Reflection.getOrCreateKotlinClass(String.class);
  if (Intrinsics.areEqual(var4, Reflection.getOrCreateKotlinClass(Integer.TYPE))) {
     var10000 = new Integer[]{1, 2, 3};
  } else {
     if (!Intrinsics.areEqual(var4, Reflection.getOrCreateKotlinClass(String.class))) {
        throw (Throwable)(new IllegalArgumentException("Invalid class: " + Reflection.getOrCreateKotlinClass(String.class).getQualifiedName()));
     }

     var10000 = new String[]{"a", "b", "c"};
  }

  String[] test2 = (String[])((Object[])var10000);
}

正确的方法--将每个类型声明为单独的非内联函数:

fun getArray(key: String, defValue: Array<Int>) : Array<Int>{
    return arrayOf(1, 2, 3)
}

fun getArray(key: String, defValue: Array<String>) : Array<String>{
    return arrayOf("a", "b", "c")
}

您必须编写稍微多一点的代码,但它没有我上面提到的任何三个问题。

这样也可以得到非常干净的字节码(小尺寸,高性能),这是反编译的字节码,与前面的示例相同,但使用了非内联函数:

public static final void testArray() {
  String var3 = "key";
  Integer[] var4 = new Integer[0];
  getArray(var3, var4);
  var3 = "key2";
  String[] var5 = new String[0];
  getArray(var3, var5);
}
 类似资料:
  • 我想具体化一个函数,我只有写好像不对 这样写好像不对

  • 函数是一个可以重复使用的代码块,CPU 会一条一条地挨着执行其中的代码。CPU 在执行主调函数代码时如果遇到了被调函数,主调函数就会暂停,CPU 转而执行被调函数的代码;被调函数执行完毕后再返回到主调函数,主调函数根据刚才的状态继续往下执行。 一个 C/ C++ 程序的执行过程可以认为是多个函数之间的相互调用过程,它们形成了一个或简单或复杂的调用链条,这个链条的起点是 main(),终点也是 ma

  • 从软件工程角度看,将程序实现为一组函数很有好处,但函数调用却会增加执行时的开销。 C++ 提供了内联函数 (inline function) 可以减少函数调用的开销,特别是对于小函数。函数定义中函数返回类型前面的限定符inline指示编译器将函数代码复制到程序中以避免函数调用。其代价是会产生函数代码的多个副本并分别插入到程序中每一个调用该函数的位置上(从而使程序更大),而不是只有一个函数副本(每次

  • FAQs in section [9]: [9.1] 内联函数有什么用? [9.2] 有没有个简单的例子说明什么是顺序集成(procedure integration)? [9.3] 内联函数能改善性能么? [9.4] 内联函数如何在安全和速度上取得折衷? [9.5] 为什么我应该用内联函数?而不是原来清晰的 #define 宏? [9.6] 如何告诉编译器使非成员函数成为内联函数? [9.7]

  • C++ 类 & 对象 C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。 如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多

  • C ++ inline函数是通常用于类的强大概念。 如果函数是内联函数,则编译器会在编译时调用函数的每个位置放置该函数的代码副本。 对内联函数的任何更改都可能需要重新编译函数的所有客户端,因为编译器需要再次替换所有代码,否则它将继续使用旧功能。 要内联函数,请在函数名称前面放置关键字inline ,并在对函数进行任何调用之前定义函数。 如果定义的函数超过一行,编译器可以忽略内联限定符。 类定义中的