繁体   English   中英

VS2010中的条件运算符正确行为?

[英]Conditional operator correct behaviour in VS2010?

我想知道这段代码是否表现出正确的C ++行为?

class Foo
{
public:
    Foo(std::string name) : m_name(name) {}

    Foo(const Foo& other) { 
        std::cout << "in copy constructor:" << other.GetName() << std::endl;
        m_name = other.GetName();
    }

    std::string GetName() const { return m_name; }
    void SetName(std::string name) { m_name = name; }

private:
    std::string m_name;
};

Foo CreateFoo(std::string name)
{
    Foo result(name);
    return result;
}

void ChangeName(Foo& foo)
{
    foo.SetName("foofoo");
}

int _tmain(int argc, _TCHAR* argv[])
{
    Foo fooA("alan");
    std::cout << "fooA name: " << fooA.GetName() << std::endl;
    bool b = true;
    ChangeName(b ? fooA : CreateFoo("fooB"));
    std::cout << "fooA name: " << fooA.GetName() << std::endl;
    return 0;
}

在VS2008中内置时,输出为:

fooA name: alan
fooA name: foofoo

但是当在VS2010中构建相同的代码时,它变为:

fooA name: alan
in copy constructor: alan
fooA name: alan

正在“alan”上调用复制构造函数,尽管通过引用传递(或者不是视情况而定),但fooA被调用的ChangeName保持不变。

C ++标准是否已更改,Microsoft是否修正了不正确的行为或是否引入了错误?

顺便说一句, 为什么要调用复制构造函数

更全面的答案:

5.16 / 4和5:

“4如果第二个和第三个操作数是左值并且具有相同的类型,则结果属于该类型并且是左值。

5否则结果是右值......“

换句话说,“bool?lvalue:rvalue”会导致暂时的。

这将是它的结束,但是你将它传递给一个函数,根据C ++,它必须接收一个左值作为参数。 因为你传递了一个rvalue,你实际上拥有的代码不是C ++。 MSVC ++接受它,因为它是愚蠢的,并使用一堆它没有告诉你的扩展,除非你把它变成一个挂件。 既然你所拥有的不是标准的C ++,并且MS只是通过扩展允许它,那么关于它的“正确”再也没有什么可说的了。

在条件表达式中,第二个操作数是Foo类型的左值 ,而第三个是Foo类型的右值 (函数的返回值不返回引用)。

这意味着条件的结果是rvalue而不是左值 (无论第一个表达式的值是什么),然后您无法将其绑定到非const引用。 由于您违反了此规则,因此无法调用语言标准来说明编译器版本的正确行为应该是什么。

条件的结果是左值如果两个第二和第三运算数是相同类型的左值

编辑:从技术上讲,两个版本都违反了标准,因为当您违反标准的可诊断规则时都没有发出诊断。

据我所知,这是由5.16第3点的C ++标准所涵盖的,不是吗?

它说“如果E2是一个右值,或者如果上面的转换不能完成:如果E1和E2有类型,并且底层类型相同或者一个是另一个的基类:E1可以转换为匹配E2如果T2的类型与T1类的基类相同,或者T2的cv资格与cv资格相同,或者cv资格等于cv资格。 T1。如果应用转换,E1将更改为T2类型的右值,该值仍然引用原始源类对象(或其相应的子对象)。[注意:即,不进行复制。]“

这不是描述上面的情况吗? 我认为确实如此,但我愿意接受,如果有人可以解释为什么不这样做,我可能会错。

谢谢。

奇怪的是,参考评论“Yep。将警告级别转为4并再次编译”。 (Noah Roberts),显然有一个警告,提供'ChangeName'采用非const引用。 如果这是一个采用const-reference的函数,那么就没有警告,但仍然创建了临时变量。 也许这只是微软编译器的另一个流行病。

编译器显然正在评估:。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM