最近,我正在深入优化我的 C++ 代码,因此开始尝试使用编译器资源管理器。由于我主要使用 Visual Studio 在 Windows 上进行开发,因此我使用了 msvc 编译器。
在某些时候 msvc 失控了。经过一番摆弄之后,我可以将其缩小到 iostream 标头,这应该是 I/O ( SL.io.3 ) 的首选。
#include <iostream>
int main() {
std::cout << "Hello World!\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
而 gcc 或 clang 的总输出(main + 一个调用一些ios_baseinit 函数的静态初始化器)总共有大约 20 行汇编代码(在 Godbolt 编译器浏览器过滤掉指令和注释之后)。
MSVC 将其分解为 4000。这些行中的大多数是单独的函数;MSVC 对main自身的定义是 7 条指令,而 gcc/clang 则是 8 条指令。(使用 GNU/Linux 的 gcc/clanglibstdc++将额外长度的 arg 传递给 cout 运算符重载函数,而不是像 MSVC 在使用自己的 C++ 库时那样只传递 2 个指针。)
如果我使用类似的东西puts,MSVC 的总输出相当紧凑,可与 gcc/clang 相媲美,就像 …
我正在使用https://godbolt.org/编译一个简单的 C++ 脚本,但即使是最简单的
int main()
{
std::cout << "Hello World!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当我点击时Add new... --> Compiler --> Output我得到:Compiler returned: 0
为了在 C++20 中使用自编模块提出问题或演示错误/功能,能够使用Matt Godbolt 的编译器资源管理器会很棒。
例子:
test.cpp(模块测试):
export module test;
export template<typename T>
void do_something(const T&)
{
}
Run Code Online (Sandbox Code Playgroud)
编译 clang++ -std=c++20 -stdlib=libc++ -fmodules -c -Xclang -emit-module-interface -o test.pcm test.cpp
主.cpp:
import test;
int main() {
do_something(7);
}
Run Code Online (Sandbox Code Playgroud)
编译 clang++ -std=c++20 -stdlib=libc++ -fmodules -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp
问:有没有办法用编译器资源管理器来做到这一点?
我在 Github 上查看了一个随机 C++ 示例(https://github.com/Quuxplusone/coro/blob/master/examples/pythagorean_triples_generator.cpp),并惊讶地发现它实际上可以编译(https://coro.cpp)。 godbolt.org/z/JXTX4Y)。
#include <https://raw.githubusercontent.com/Quuxplusone/coro/master/include/coro/shared_generator.h>
#include <stdio.h>
#include <tuple>
#include <range/v3/view/take.hpp>
namespace rv = ranges::view;
auto triples() -> shared_generator<std::tuple<int, int, int>> {
for (int z = 1; true; ++z) {
for (int x = 1; x < z; ++x) {
for (int y = x; y < z; ++y) {
if (x*x + y*y == z*z) {
co_yield std::make_tuple(x, y, z);
}
}
}
}
}
int main() {
for (auto&& triple : …Run Code Online (Sandbox Code Playgroud) 我正在编写一个需要在运行时创建数组的函数。该数组将是小尺寸,因此我不担心不安全的代码,但是,我想编写“正确”的代码。因此,我正在考虑三种选择:
使用Compiler Explorer将它们与 -O3 进行比较。结果如下:
我是否错过了对 std::vector<> 的优化,或者“正确的”C++ 方式是否较慢,或者我完全错过了一种编码方式?
编辑:我忘了删除堆分配的数组
测试代码:
代码1:
#include <string.h>
void populate_array(char* arr);
int compute_result(char* arr);
int str_to_arr(const char* str)
{
auto len = strlen(str);
char array[len];
populate_array(array);
return compute_result(array);
}
Run Code Online (Sandbox Code Playgroud)
代码2:
#include <string.h>
void populate_array(char* arr);
int compute_result(char* arr);
int str_to_arr(const char* str)
{
auto len = strlen(str);
char* array = new char[len];
populate_array(array);
auto result = compute_result(array);
delete[] array;
return …Run Code Online (Sandbox Code Playgroud) 我想在本地生成像编译器资源管理器这样的干净程序集。请注意,我阅读了如何从 GCC/clang 程序集输出中删除“噪音”?在尝试之前。与 Godbolt 相比,使用该方法的输出没有那么干净或密集,并且仍然有很多 asm 指令和未使用的标签。
如何在没有任何未使用的标签或指令的情况下获得干净的汇编输出?
从https://github.com/gcc-mirror/gcc/commit/3acb929cc0beb79e6f4005eb22ee88b45e1cbc1d提交来看,C++ 标准头<stacktrace>存在诸如此类的东西,std::stacktrace_entry但没有声明,因为_GLIBCXX_HAVE_STACKTRACE也没有定义。
我已经在https://godbolt.org/z/b9TvEMYnh上尝试过,但是一旦我添加了参数,就会发出链接器错误-lstd++_libbacktrace(ofc,未找到)
#include <stacktrace> // header found
int main() {
// can't use features like 'std::stacktrace_entry' and 'std::stacktrace'
}
Run Code Online (Sandbox Code Playgroud)
从提交描述来看,这条消息意味着什么?:
目前,只有使用 --enable-libstdcxx-backtrace=yes 时才会构建新库。
正如标题所示。比如说,我想通过Godbolt项目来做到这一点:
main.cpp
#include <iostream>
extern "C" int test_111();
int main()
{
int r = test_111();
std::cout << "result=" << r << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后在asm1.asm:
.code
test_111 PROC
; 64-bit assembly
xor eax, eax
inc rax
ret
test_111 ENDP
END
Run Code Online (Sandbox Code Playgroud)
在“x86-64 clang”(任何版本)下尝试。
但我似乎不知道如何做到这一点。有什么建议么?
附言。目标是将我自己的汇编指令注入到输出中。
编辑:
在评论中提出建议后,我尝试了关键词asm volatile,但它只是将我放入其中的任何乱码添加到程序集输出中:
我想在编译器资源管理器 (godbolt.org) 上运行一个 C 项目,其中包含一些外部头文件。包含这些第三方头文件的过程是什么?
假设我想运行包含 snipmath.h 文件的代码。此外,snipmath.h 标头还包含其他 lib 文件。我怎样才能将它们全部包含在 godbolt 中?就像我们通常在离线编译器中所做的那样。
根据convertible_to中的 en.cppreference.com :
概念convertible_to<From, To>指定与std::declval()相同类型和值类别的表达式可以隐式和显式转换为To类型,并且两种转换形式是等效的。
我理解这意味着如果有成员,该convertible_to概念将被识别convertible_to<U, V>为满意。即使运算符是显式的而不是隐式运算符。Uexplicit operator V()
但是我发现msvc中不是这样的。
由于静态断言,以下代码无法编译:
#include <concepts>
#include <iostream>
class ExplictClass
{
public:
inline explicit operator int() const
{
return 5;
}
};
int main()
{
static_assert(std::convertible_to<ExplictClass, int>, "Explicit not convertible?"); // Fails here, concept not satisfied.
}
Run Code Online (Sandbox Code Playgroud)
这是我对概念的误解std::convertible_to,代码中的错误,还是 en.cppreference.com 中的错误,或者 msvc v19 的不一致性。
附上使用 x64 msvc v19.latest 的编译器资源管理器的链接,其中包含上述代码
编辑:
实际需要convertible_to是生成一个to_string函数模板,该模板可以与声明的可转换类型很好地配合,如下所示:
template<class T>
std::string to_string(T val)
{
std::ostringstream stream; …Run Code Online (Sandbox Code Playgroud)