相关疑难解决方法(0)

编译器优化未使用字符串的行为不一致

我很好奇为什么下面的代码:

#include <string>
int main()
{
    std::string a = "ABCDEFGHIJKLMNO";
}
Run Code Online (Sandbox Code Playgroud)

当使用编译时,将-O3产生以下代码:

main:                                   # @main
    xor     eax, eax
    ret
Run Code Online (Sandbox Code Playgroud)

(我完全理解不需要多余的,a因此编译器可以从生成的代码中完全忽略它)

但是以下程序:

#include <string>
int main()
{
    std::string a = "ABCDEFGHIJKLMNOP"; // <-- !!! One Extra P 
}
Run Code Online (Sandbox Code Playgroud)

产量:

main:                                   # @main
        push    rbx
        sub     rsp, 48
        lea     rbx, [rsp + 32]
        mov     qword ptr [rsp + 16], rbx
        mov     qword ptr [rsp + 8], 16
        lea     rdi, [rsp + 16]
        lea     rsi, [rsp + 8]
        xor …
Run Code Online (Sandbox Code Playgroud)

c++ gcc compilation clang compiler-optimization

69
推荐指数
2
解决办法
2894
查看次数

编译器可以从堆优化到堆栈分配吗?

就编译器优化而言,将堆分配更改为堆栈分配是否合法和/或可能?或者会破坏as-if规则

例如,假设这是代码的原始版本

{
    Foo* f = new Foo();
    f->do_something();
    delete f;
}
Run Code Online (Sandbox Code Playgroud)

编译器是否能够将此更改为以下内容

{
    Foo f{};
    f.do_something();
}
Run Code Online (Sandbox Code Playgroud)

我不这么认为,因为如果原始版本依赖于自定义分配器之类的东西,那将会产生影响.标准是否对此有具体说明?

c++ memory-management compiler-optimization language-lawyer

63
推荐指数
2
解决办法
3085
查看次数

我应该将std :: string与“ string”或“ string” s比较吗?

考虑以下代码片段:

bool foo(const std::string& s) {
    return s == "hello"; // comparing against a const char* literal
}

bool bar(const std::string& s) {
    return s == "hello"s; // comparing against a std::string literal
}
Run Code Online (Sandbox Code Playgroud)

乍一看,它看起来像比对并const char*需要更少的组装说明1,作为使用字符串字面量会导致就地建设std::string

编辑:正如答案中指出的那样,我忘记了有效地s.compare(const char*)将被调用的事实foo(),因此在这种情况下当然不会进行就地构建。因此,请在下面删除一些行。

但是,请operator==(const char*, const std::string&)参阅参考资料:

所有比较都是通过compare()成员函数完成的。

根据我的理解,这意味着我们将需要构造一个结构std::string来执行比较,因此我怀疑最终的开销将是相同的(尽管对的调用已将其隐藏了operator==)。

  • 我应该选择哪个比较?
  • 一个版本是否比另一个版本具有优势(可能在特定情况下)?

1我知道更少的汇编指令并不一定意味着更快的代码,但是我不想在这里进行微基准测试。

c++ string-comparison string-literals c++14 c++17

44
推荐指数
3
解决办法
2894
查看次数

为什么这个未使用的变量没有被优化掉?

我玩过Godbolt的CompilerExplorer.我想看看某些优化是多么好.我的最低工作范例是:

#include <vector>

int foo() {
    std::vector<int> v {1, 2, 3, 4, 5};
    return v[4];
}
Run Code Online (Sandbox Code Playgroud)

生成的汇编程序(通过clang 5.0.0,-O2 -std = c ++ 14):

foo(): # @foo()
  push rax
  mov edi, 20
  call operator new(unsigned long)
  mov rdi, rax
  call operator delete(void*)
  mov eax, 5
  pop rcx
  ret
Run Code Online (Sandbox Code Playgroud)

可以看出,clang知道答案,但在返回之前会做很多事情.在我看来,即使是矢量也是由于"operator new/delete"而创建的.

任何人都可以向我解释这里发生了什么以及它为什么不回归?

GCC生成的代码(此处未复制)似乎明确构造了向量.有谁知道海湾合作委员会无法推断出结果?

c++ gcc clang compiler-optimization

38
推荐指数
2
解决办法
3076
查看次数

为什么 a=[0] 的 list(x for x in a) 比 a=[] 快?

list(x for x in a)用三个不同的 CPython 版本进行了测试。Ona = [0]比 on 快得多a = []

 3.9.0 64-bit       3.9.0 32-bit       3.7.8 64-bit
a = []  a = [0]    a = []  a = [0]    a = []  a = [0]

465 ns  412 ns     543 ns  515 ns     513 ns  457 ns   
450 ns  406 ns     544 ns  515 ns     506 ns  491 ns   
456 ns  408 ns     551 ns  513 ns     515 ns  487 ns   
455 …
Run Code Online (Sandbox Code Playgroud)

python performance cpython python-internals

36
推荐指数
1
解决办法
822
查看次数

Stroustrup书和C++标准之间的明显矛盾

我试图理解Stroustrup的"The C++ Programming Language"(第282页)中的以下段落(重点是我的):

要解除分配new,delete和delete []分配的空间,必须能够确定分配的对象的大小.这意味着使用new的标准实现分配的对象将占用比静态对象稍多的空间.至少需要空间来保持物体的大小.通常每个分配有两个或更多个单词用于免费商店管理.大多数现代机器使用8字节字.当我们分配许多对象或大对象时,这种开销并不重要,但是如果我们在免费商店中分配大量小对象(例如,int或Points)则可能很重要.

请注意,作者没有在上面突出显示的句子中区分对象是否是数组.

但是根据C++ 14中的段落§5.3.4/ 11,我们(我的重点):

当new-expression调用分配函数并且尚未扩展分配时,new-expression将请求的空间量作为std :: size_t类型的第一个参数传递给分配函数.该参数不得小于正在创建的对象的大小; 当对象是数组时,它可能大于正在创建的对象的大小.

我可能会遗漏一些东西,但在我看来,我们在这两个陈述中都存在矛盾.据我所知,所需的额外空间仅用于数组对象,并且这个额外的空间将保存数组中的元素数,而不是数组的大小(以字节为单位).

c++ memory-management c++14

21
推荐指数
2
解决办法
1872
查看次数

是否保证std :: vector默认构造不会调用new?

根据引用,simple std::vector<T> vec;创建了一个emtpy容器(默认构造函数).这是否保证没有动态内存分配?或者一个实现可能选择保留一些内存?

我知道,对于这个空构造函数,T自C++ 11以来没有类型的构造.但是,我想知道,如果还保证堆上没有分配任何内容.即上面的行只是nullptr堆栈/成员上的几个.

我用vc140测试了它,它确实没有动态分配.

c++ memory-management stdvector

20
推荐指数
2
解决办法
1827
查看次数

C++编译器是否对lambda闭包执行编译时优化?

假设我们有以下(无意义)代码:

const int a = 0;
int c = 0;
for(int b = 0; b < 10000000; b++)
{
    if(a) c++;
    c += 7;
}
Run Code Online (Sandbox Code Playgroud)

变量'a'等于零,因此编译器可以在编译时推断出指令'if(a)c ++;' 将永远不会被执行,并将优化它.

我的问题:lambda闭包会发生同样的情况吗?

查看另一段代码:

const int a = 0;
function<int()> lambda = [a]()
{
    int c = 0;
    for(int b = 0; b < 10000000; b++)
    {
        if(a) c++;
        c += 7;
    }
    return c;
}
Run Code Online (Sandbox Code Playgroud)

编译器是否会知道'a'是0并且它会优化lambda吗?

更复杂的例子:

function<int()> generate_lambda(const int a)
{
    return [a]()
    {
        int c = 0;
        for(int b = …
Run Code Online (Sandbox Code Playgroud)

c++ optimization lambda gcc llvm-clang

10
推荐指数
1
解决办法
1025
查看次数

通过值,引用和右值传递字符串

我只是比较将字符串传递给函数的性能。该基准测试结果很有趣。

这是我的代码:

void add(std::string msg)
{
    msg += "world";
}

void addRvalue(std::string&& msg)
{
    msg += "world";
}

void addRef(std::string& msg)
{
    msg += "world";
}

void StringCreation() {
    add(std::string("hello "));
}

void StringCopy() {
    std::string msg("hello ");
    add(msg);
}

void StringMove() {
    std::string msg("hello ");
    add(std::move(msg));
}

void StringRvalue() {
    std::string msg("hello ");
    addRvalue(std::move(msg));
}

void StringReference() {
    std::string msg("hello ");
    addRef(msg);
}
Run Code Online (Sandbox Code Playgroud)

StringCreation(),StringRvalue()和StringReference()是等效的。我很惊讶StringMove()是性能最低的-比涉及复制的值传递差。

我是否认为调用StringMove()涉及一个移动构造函数,然后在调用add()时涉及一个复制构造函数,对吗?它不仅仅涉及一举动的构造函数吗?我以为搬家的建设很便宜。

更新资料

我增加了传递给add()的字符串的长度,这确实有所作为。现在,StringMove()仅比StringCreation和StringReference慢1.1倍。StringCopy现在是最糟糕的,这正是我所期望的。

这是新的基准测试结果

因此,StringMove根本不涉及复制-仅适用于小字符串。

c++ stdstring c++11

9
推荐指数
1
解决办法
169
查看次数

Visual C++优化选项 - 如何改进代码输出?

是否有任何选项(/ O2除外)来改进Visual C++代码输出?在这方面,MSDN文档非常糟糕.请注意,我不是在询问项目范围的设置(链接时优化等).我只对这个特殊的例子感兴趣.

相当简单的C++ 11代码如下所示:

#include <vector>
int main() {
    std::vector<int> v = {1, 2, 3, 4};
    int sum = 0;
    for(int i = 0; i < v.size(); i++) {
        sum += v[i];
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

Clang的libc ++输出非常紧凑:

main: # @main
  mov eax, 10
  ret
Run Code Online (Sandbox Code Playgroud)

另一方面,Visual C++输出是一个多页面的混乱.我在这里遗漏了什么,还是VS真的很糟糕?

编译器资源管理器链接:https: //godbolt.org/g/GJYHjE

c++ visual-c++ c++11 cl

8
推荐指数
1
解决办法
1744
查看次数