clang和gcc之间const参考三元运算符的地址差异

nev*_*stn 5 c++ gcc ternary-operator clang++

我对这里发生的事情有一个模糊的想法......它与此有关,但我想知道为什么clang ++和g ++处理这个问题的方式不同.这里的未定义行为在哪里?注意:这与模板无关 - 我只是使用它们来使示例更紧凑.这都是关于它的类型whatever.

#include <iostream>
#include <vector>

template <typename T>
void test()
{
    T whatever = 'c';


    const char a = 'a';

    std::cout << "begin: " << (void*)&a << std::endl;

    const char & me = (true ? a : whatever);

    std::cout << "ref:   " << (void*)&me << std::endl;
}

int main(int argc, char**argv)
{

    test<const char>();
    test<char>();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

gcc输出(测试高达4.9.3):

begin: 0x7fffe504201f
ref:   0x7fffe504201f
begin: 0x7fffe504201e
ref:   0x7fffe504201f
Run Code Online (Sandbox Code Playgroud)

clang 3.7.0输出:

begin: 0x7ffed7b6bb97
ref:   0x7ffed7b6bb97
begin: 0x7ffed7b6bb97
ref:   0x7ffed7b6bb97
Run Code Online (Sandbox Code Playgroud)

M.M*_*M.M 0

今天在另一个问题中的回答详细介绍了您的案例。我将避免重复自己,只是进行总结。

如果我们分解出模板,就会有两种情况。情况1:

const char whatever = 'c';
const char a = 'a';
const char & me = (true ? a : whatever);
Run Code Online (Sandbox Code Playgroud)

条件运算符的第二个和第三个操作数都是“类型的左值const char”,因此结果是const char指定所选操作数的“类型的左值”。最后,const char &直接绑定到“类型的左值const char”,因此&me== &a

对于情况2:

char whatever = 'c';
const char a = 'a';
const char & me = (true ? a : whatever);
Run Code Online (Sandbox Code Playgroud)

第二个和第三个操作数是“类型的左值char”和“类型的左值const char”。其结果是const char指定所选操作数的“类型左值”。和以前一样,const char &me直接绑定到类型 的左值const char,因此&me == &a

如果编译器在任一情况下打印不同的地址mea则这是一个编译器错误。