花括号初始化会防止对临时变量进行非const使用。

12

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

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

int main() {
    const S a{};
    S{a}.f(); // Error on this line
    return 0;
}

使用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

这两个变体在gcc中都可以编译通过。我是不是漏掉了什么,还是这是一个编译器的错误?


2
你使用哪个版本的C++来编译你的代码?假设是C++11。 - Ely
通知:g++ 5.1.0 编译正常。 - Richard Critten
这就是 MSVC 给你的: - xinaiz
@Elyasin 我正在以C++14编译此代码。 - Beta Carotin
2个回答

3
似乎又是一个MSVC的bug。 S{a}被推断为const struct S,这本身就是一个错误。
#include <string>
#include <iostream>

template < class T >
std::string type_name()
{
    std::string p = __FUNCSIG__;
    return p.substr( 106, p.length() - 106 - 7 );
}


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

int main() {
    const S a{};
    //S{a}.f(); // Error on this line
    std::cout << type_name<decltype(S{a})>() << std::endl;
    return 0;
}

输出:

const struct S

如果您能提供错误的链接原因,我将不胜感激。 - Ely
1
@Elyasin 这是一个错误,因为根本不应该有类型推导。直接列表初始化不会推导类型。 - Nicol Bolas

2

看起来像是编译器的错误,或者奇怪优化的结果,因为这个只有构造函数和析构函数带有副作用的原始代码变体在使用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;
}

编译成功,输出结果为:
Default ctor 0306FF07
Copy ctor 0306FF07 -> 0306FF06
Dtor 0306FF06
Dtor 0306FF07

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接