Brace初始化可防止非常量使用临时

Bet*_*tin 12 c++ temporary list-initialization

我想创建一个const对象的临时副本,并以非const方式使用它:

struct S {
    S& f() { return *this; }
};

int main() {
    const S a{};
    S{a}.f(); // Error on this line
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用msvc(Visual Studio 2017,C++ 14),我收到此错误:

错误C2662'S&S :: f(void)':无法将'this'指针从'const S'转换为'S&'

如果我将大括号初始化更改为经典初始化,它可以工作:

S{a}.f(); // Does not work
S(a).f(); // Works
Run Code Online (Sandbox Code Playgroud)

两种变体在gcc中编译都很好.我错过了什么或这是一个编译器错误?

Ser*_*sta 2

它看起来像是一个编译器错误,或者是一个奇怪的优化的结果,因为原始代码的这种变体只使 ctors 和 dtor 具有副作用,可以使用 MSVC 很好地编译:

#include <iostream>

struct S {
    S(const S& other) {
        std::cout << "Copy ctor " << &other << " -> " << this << std::endl;
    }
    S() {
        std::cout << "Default ctor " << this << std::endl;
    }
    ~S() {
        std::cout << "Dtor " << this << std::endl;
    }
    S& f() { return *this; }
};

int main() {
    const S a{};
    std::cout << &a << std::endl;
    S{a}.f();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译成功,输出为:

#include <iostream>

struct S {
    S(const S& other) {
        std::cout << "Copy ctor " << &other << " -> " << this << std::endl;
    }
    S() {
        std::cout << "Default ctor " << this << std::endl;
    }
    ~S() {
        std::cout << "Dtor " << this << std::endl;
    }
    S& f() { return *this; }
};

int main() {
    const S a{};
    std::cout << &a << std::endl;
    S{a}.f();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)