这是一段看似非常特殊的C++代码.出于某种奇怪的原因,奇迹般地对数据进行排序使得代码几乎快了六倍.
#include <algorithm>
#include <ctime>
#include <iostream>
int main()
{
// Generate data
const unsigned arraySize = 32768;
int data[arraySize];
for (unsigned c = 0; c < arraySize; ++c)
data[c] = std::rand() % 256;
// !!! With this, the next loop runs faster.
std::sort(data, data + arraySize);
// Test
clock_t start = clock();
long long sum = 0;
for (unsigned i = 0; i < 100000; ++i)
{
// Primary loop
for (unsigned c = 0; c < arraySize; ++c) …Run Code Online (Sandbox Code Playgroud) 我为Project Euler Q14编写了这两个解决方案,在汇编和C++中.它们是用于测试Collatz猜想的相同蛮力方法.装配解决方案与组装
nasm -felf64 p14.asm && gcc p14.o -o p14
Run Code Online (Sandbox Code Playgroud)
C++是用.编译的
g++ p14.cpp -o p14
Run Code Online (Sandbox Code Playgroud)
部件, p14.asm
section .data
fmt db "%d", 10, 0
global main
extern printf
section .text
main:
mov rcx, 1000000
xor rdi, rdi ; max i
xor rsi, rsi ; i
l1:
dec rcx
xor r10, r10 ; count
mov rax, rcx
l2:
test rax, 1
jpe even
mov rbx, 3
mul rbx
inc rax
jmp c1
even:
mov rbx, 2 …Run Code Online (Sandbox Code Playgroud) 这是一位高级经理提出的面试问题.
哪个更快?
while(1) {
// Some code
}
Run Code Online (Sandbox Code Playgroud)
要么
while(2) {
//Some code
}
Run Code Online (Sandbox Code Playgroud)
我说两者都有相同的执行速度,因为里面的表达式while应该最终评估为true或false.在这种情况下,两者都评估,true并且条件内没有额外的条件指令while.因此,两者都具有相同的执行速度,而我更喜欢(1).
但采访者自信地说:"检查你的基础知识.while(1)比快while(2)." (他没有测试我的信心)
这是真的?
我用 C 语言实现了一个冒泡排序,并在测试其性能时发现该-O3标志使其运行速度甚至比没有标志时还要慢!与此同时-O2,它的运行速度比预期的要快得多。
没有优化:
time ./sort 30000
./sort 30000 1.82s user 0.00s system 99% cpu 1.816 total
Run Code Online (Sandbox Code Playgroud)
-O2:
time ./sort 30000
./sort 30000 1.00s user 0.00s system 99% cpu 1.005 total
Run Code Online (Sandbox Code Playgroud)
-O3:
time ./sort 30000
./sort 30000 2.01s user 0.00s system 99% cpu 2.007 total
Run Code Online (Sandbox Code Playgroud)
代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
int n;
void bubblesort(int *buf)
{
bool changed = true;
for (int i = n; changed == true; …Run Code Online (Sandbox Code Playgroud) 我正在准备 C++ 入门课程的期末考试。我们的教授给了我们这个问题来练习:
解释为什么代码会产生以下输出:
120 200 16 0
using namespace std;
int main()
{
int x[] = {120, 200, 16};
for (int i = 0; i < 4; i++)
cout << x[i] << " ";
}
Run Code Online (Sandbox Code Playgroud)
该问题的示例答案是:
cout 语句只是循环遍历其下标由 for 循环的增量定义的数组元素。元素大小不是由数组初始化定义的。for 循环定义了数组的大小,该大小恰好超出了初始化元素的数量,因此最后一个元素默认为零。第一个 for 循环打印元素 0 (120),第二个循环打印元素 1 (200),第三个循环打印元素 2 (16),第四个循环打印默认数组值零,因为元素 3 没有任何初始化。现在 i 点超出了条件并且 for 循环终止。
我有点困惑为什么数组之外的最后一个元素总是“默认”为零。为了进行实验,我将问题中的代码粘贴到我的 IDE 中,但将 for 循环更改为for (int i = 0; i < 8; i++). 然后输出更改为120 200 16 0 4196320 0 …
c++ arrays initialization undefined-behavior zero-initialization
与C++ 11中的普通指针相比,智能指针的开销是多少?换句话说,如果我使用智能指针,我的代码会变慢吗?如果是这样,速度会慢多少?
具体来说,我问的是C++ 11 std::shared_ptr和std::unique_ptr.
显然,推下堆栈的东西会变得更大(至少我认为是这样),因为智能指针也需要存储其内部状态(引用计数等),问题是,这是多少影响我的表现,如果有的话?
例如,我从函数而不是普通指针返回一个智能指针:
std::shared_ptr<const Value> getValue();
// versus
const Value *getValue();
Run Code Online (Sandbox Code Playgroud)
或者,例如,当我的一个函数接受智能指针作为参数而不是普通指针时:
void setValue(std::shared_ptr<const Value> val);
// versus
void setValue(const Value *val);
Run Code Online (Sandbox Code Playgroud) 我想检查boost::variant在我的代码中应用的程序集输出,以便查看哪些中间调用被优化掉了.
当我编译以下示例(使用GCC 5.3 g++ -O3 -std=c++14 -S)时,似乎编译器优化了所有内容并直接返回100:
(...)
main:
.LFB9320:
.cfi_startproc
movl $100, %eax
ret
.cfi_endproc
(...)
Run Code Online (Sandbox Code Playgroud)
#include <boost/variant.hpp>
struct Foo
{
int get() { return 100; }
};
struct Bar
{
int get() { return 999; }
};
using Variant = boost::variant<Foo, Bar>;
int run(Variant v)
{
return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
Foo f;
return run(f);
}
Run Code Online (Sandbox Code Playgroud)
但是,完整的程序集输出包含的内容远远超过上面的摘录,对我而言,它看起来永远不会被调用.有没有办法告诉GCC/clang删除所有"噪音"并输出程序运行时实际调用的内容?
完整装配输出:
.file "main1.cpp"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC0:
.string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
.section .rodata.str1.1,"aMS",@progbits,1
.LC1: …Run Code Online (Sandbox Code Playgroud) 不久,我想知道gcc(或g ++.我需要它在C中,但也很好奇c ++)定义任何特殊符号如果-g启用.可以?如果是这样,有什么符号?
在搜索过程中,我发现:
_DEBUG是手动定义的(通过手动我的意思-D_DEBUG)并且是从Visual C程序员那里习惯的习惯(因为VC _DEBUG在调试模式下编译时定义)NDEBUG如果不在调试模式下,则定义.虽然我发现有几个地方在说这个,但是我在.c和.cpp文件中尝试使用我的gcc和g ++,并且在-g没有这些符号的情况下都没有定义这样的符号!编辑:让我演示为什么我不想使用非标准符号:
想象一下内核模块做了什么,并提供了包含在其他内核模块中的头文件,以便它们可以连接到这个.
现在作为一个工具,我在其中一个头文件中:
#ifdef DEBUG <-- This is what I need
#define LOG(x, ...) printk("Some extra info"x, ##__VA_ARGS__);
#else
#define LOG(x, ...) printk("Without extra info"x, ##__VA_ARGS__);
#endif
Run Code Online (Sandbox Code Playgroud)
请注意,名称不是真的LOG,这是一个例子.
现在,我可以为DEBUG自己使用任何符号,但如果有人包含我的标题,他们可能无法定义该符号.当然,我可以告诉他们"顺便说一句,在调试模式中获取标题,定义另一个符号",但这对我来说听起来不对.
我可以在标头中定义符号并将其包含在所有头文件中.这样,如果它们包含我的一个标题,它们也会得到调试符号.现在的问题是,如果他们不希望在调试模式下进行编译,我的头仍然认为他们是在调试模式.
所以我认为最好的是使用在使用时定义的符号-g,如果有的话!
到目前为止,我得出结论,我可以这样做:
how_to_build.h
#if !defined(NDEBUG)
#define MY_DEBUG
#endif
Run Code Online (Sandbox Code Playgroud)
用法:
#include "how_to_build.h"
#ifdef MY_DEBUG
// rest of the story
Run Code Online (Sandbox Code Playgroud)
这样,通用选项也NDEBUG …
我经常听到这种说法,现代硬件上的乘法是如此优化,以至于它实际上与加法相同.真的吗?
我从来没有得到任何权威的确认.我自己的研究只会增加问题.速度测试通常会显示让我感到困惑的数据.这是一个例子:
#include <stdio.h>
#include <sys/time.h>
unsigned int time1000() {
timeval val;
gettimeofday(&val, 0);
val.tv_sec &= 0xffff;
return val.tv_sec * 1000 + val.tv_usec / 1000;
}
int main() {
unsigned int sum = 1, T = time1000();
for (int i = 1; i < 100000000; i++) {
sum += i + (i+1); sum++;
}
printf("%u %u\n", time1000() - T, sum);
sum = 1;
T = time1000();
for (int i = 1; i < 100000000; i++) {
sum += i * …Run Code Online (Sandbox Code Playgroud)