当我在C中编写面向对象的代码时,我通常将结构定义与公共函数一起放在头文件中,并在单独的.c文件中实现公共函数.我将static关键字赋给此类的所有"私有"函数,并在.c文件中实现它们.然后,公共函数可以调用属于同一类的私有函数.由于static关键字,私有函数无法从外部调用,因此GCC可以优化其中许多函数.它们经常被内联,原始函数完全从输出对象文件中删除.
现在我的问题是:我怎么能用C++类做同样的事情?
假设我有一个头文件:
class A {
int private_field;
int private_function();
public:
int public_function();
};
Run Code Online (Sandbox Code Playgroud)
我的.cpp文件:
#include <iostream>
#include "A.h"
int A::private_function() {
std::cin >> private_field;
return private_field;
}
int A::public_function() {
return private_function() + 4;
}
Run Code Online (Sandbox Code Playgroud)
在生成的目标文件中,private_function保留为单独的符号,public_function调用private_function(未内联).我想提供private_function内部链接,因此编译器可以执行与使用C时相同的优化.我尝试过使用匿名命名空间和静态,但我无法按照我的意愿使用它.如何正确地做到这一点,甚至可能吗?我用GCC.
正如问题lambda capture by value mutable 中所见,它不适用于 const &? , 当const T&使用其名称或[=]可变 lambda捕获类型的值时,隐藏类中的字段获取类型const T。可以争论的是,这对于可变 lambda 来说是正确的做法。
但是为什么对非可变 lambda 也这样做呢?在非可变 lambda 表达式中,operator()(...)is 被声明const,因此无论如何它都不能修改捕获的值。
当我们移动 lambda 时,例如将它包装在std::function.
请参阅以下两个示例:
#include <cstdio>
#include <functional>
std::function<void()> f1, f2;
struct Test {
Test() {puts("Construct");}
Test(const Test& o) {puts("Copy");}
Test(Test&& o) {puts("Move");}
~Test() {puts("Destruct");}
};
void set_f1(const Test& v) {
f1 = [v] () {}; // field type in lambda object will be …Run Code Online (Sandbox Code Playgroud) 我正在阅读 JVM 版本 8 规范的第 4.10.2.2 节(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html)如何验证字节码。在这种情况下,当堆栈现在包含一个槽时,如果来自一个源,则包含一个 int[] ;如果来自另一个源,则包含一个 String[] ,控制流中会发生什么情况。
我阅读了以下内容,该内容在 JVM 版本 7 文档中不存在:
如果对应的值都是数组引用类型,则检查它们的维度。如果数组类型具有相同的维度,则合并的值是对数组类型实例的引用,该数组类型是两种数组类型的第一个公共超类型。(如果其中一个或两个数组类型具有原始元素类型,则使用 Object 作为元素类型。)
...
甚至int[]和String[]也可以合并;结果是 Object[],因为在计算第一个公共超类型时使用了 Object 而不是 int。
这对我来说没有任何意义,因为这意味着 int[] 可以转换为 Object[]。但在 Java 中,原始类型的数组不能转换为 Object[]。
谁能解释一下这背后的理由吗?
当我发出LLVM代码时,我应该避免使用'insertvalue'指令结合加载和存储吗?当我使用它时,我总是得到错误的优化本机代码.请看以下示例:
; ModuleID = 'mod'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-pc-linux-gnu"
%A = type { i64, i64, i64, i64, i64, i64, i64, i64 }
@aa = external global %A*
define void @func() {
entry:
%a1 = load %A** @aa
%a2 = load %A* %a1
%a3 = insertvalue %A %a2, i64 3, 3
store %A %a3, %A* %a1
ret void
}
Run Code Online (Sandbox Code Playgroud)
当我运行"llc -o - -O3 mod.ll"时,我得到了这个可怕的代码:
func: # @func
.Ltmp0:
.cfi_startproc
# BB#0: # %entry
movq aa(%rip), %rax
movq …Run Code Online (Sandbox Code Playgroud) 我正在编写一个使用LLVM作为后端的编译器,并且有很多引用计数.当我借用一个对象时,我会增加对象的引用计数器.当我释放一个对象时,我减少了参考计数器,并在它变为零时释放该对象.但是,如果我只做一小段代码,就像这样:
++obj->ref;
global_variable_A = obj->a;
if (--obj->ref == 0)
free_object(obj);
Run Code Online (Sandbox Code Playgroud)
LLVM将此优化为(在IR中,但这是C中的相等代码):
global_variable_A = obj->a;
if (obj->ref == 0)
free_object(obj);
Run Code Online (Sandbox Code Playgroud)
但是因为我知道在第一个语句之前引用计数器总是正数,所以它只能被优化
global_variable_A = obj->a;
Run Code Online (Sandbox Code Playgroud)
我的问题:有没有办法告诉LLVM优化器,在读取它时,寄存器或某些内存是否包含非零数据?
另一个相同的问题是,如果我可以告诉优化器指针是非空的,那也很好.
我在 Linux 上使用 OpenJDK 11,我需要确保使用 HttpURLConnection 完成的所有 Web 请求都已正确关闭,并且不打开任何文件描述符。
甲骨文手册讲述使用close上InputStream和Android的手册告诉编译器使用disconnect的上HttpURLConnection对象。
我还设置Connection: close和http.keepAlive以false避免连接池。
这似乎适用于普通的http请求,但不适用于其响应以非分块编码发送的加密https请求。似乎只有 GC 会清理关闭的连接。
此示例代码:
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class Test {
private static int printFds() throws IOException {
int cnt = 0;
try (Stream<Path> paths = Files.list(new File("/proc/self/fd").toPath())) {
for …Run Code Online (Sandbox Code Playgroud)