使用列表初始化时,C++语言是否强制执行编译器优化?

Car*_*sel 3 c++ optimization gcc clang list-initialization

这是source.cpp

#include <iostream>

struct A {
    A(int i) : i(i) { std::cout << this << ": A(int)" << std::endl; }
    A(A const &a) : i(a.i) { std::cout << this << ": A(A const &)" << std::endl; }
    A(A &&a) : i(a.i) { std::cout << this << ": A(A &&)" << std::endl; }
    ~A() { std::cout << this << ": ~A()" << std::endl; }    

  private:
    int i;
};    

int main() {
    std::cout << "#1 :" << std::endl;
    A a1 = 1; // #1, copy-initialization    

    std::cout << "#2 :" << std::endl;
    A a3(1); // #2, direct-initialization    

    std::cout << "#3 :" << std::endl;
    A a4 = {1}; // #3, copy-list-initialization    

    std::cout << "#4 :" << std::endl;
    A a5{1}; // #4, direct-list-initialization    

    std::cout << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译上面的代码clang++ -std=c++14 -Wall -fno-elide-constructors -pedantic -o main.exe source.cpp(这里,我禁用了构造优化.顺便说一下,我正在使用Clang 3.8.1).然后,我得到以下输出:

#1 :
0x61fe40: A(int)
0x61fe48: A(A &&)
0x61fe40: ~A()
#2 :
0x61fe30: A(int)
#3 :
0x61fe28: A(int)
#4 :
0x61fe20: A(int)

0x61fe20: ~A()
0x61fe28: ~A()
0x61fe30: ~A()
0x61fe48: ~A()
Run Code Online (Sandbox Code Playgroud)

让我感到高兴的是#3不会A::A(int)先调用然后调用A::A(A &&)#1,尽管它们都是复制初始化的.我还用gcc 6.1.0测试了它.同样的事情发生了 据我所知,列表初始化的一个常见用法是禁止缩小转换.我不知道它有任何与编译优化相关的东西.所以,

C++语言在使用列表初始化时是否强制执行编译器优化,或者只是编译器更喜欢这样做或其他原因导致上述行为?

use*_*267 5

在这种情况下,直接和复制列表初始化都会导致对构造函数的调用.

在[dcl.init.list]/3的规则中使用消除过程,

对象或类型引用的列表初始化T定义如下:

[...]

否则,如果T是类类型,则考虑构造函数.枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数.如果转换任何参数需要缩小转换(见下文),则程序格式错误.

重要的是复制初始化和复制列表初始化不等效,您可以使用复制列表初始化来初始化具有已删除副本的对象并移动构造函数,例如:

struct A
{
  A(int i){}
  A(A const&) =delete;
  A(A&&) =delete;
};    

int main()
{
  A a1 = {1};
  A a2 = 1; // won't compile
}
Run Code Online (Sandbox Code Playgroud)