虚拟功能的反直觉行为

mos*_*ear 1 c++

特定

#include <string>
#include <iostream>


struct A  {
    virtual operator std::string() const { return "A"; }
    virtual operator const char *() const { return this->operator std::string().c_str(); }
};

struct B1 : public A {
    virtual operator std::string() const { return "<"; }
};

struct B2 {
    B2() { }
    virtual ~B2() { }
    virtual operator std::string() const { return ">"; }
    virtual operator const char *() const { return this->operator std::string().c_str(); }
};

struct C1 : public A {
    C1() { }
    virtual ~C1() { }
    virtual operator std::string() const { return "["; }
};

struct C2 {
    C2() { }
    virtual ~C2() { }
    virtual operator std::string() const { return "]"; }
    virtual operator const char *() const { return this->operator std::string().c_str(); }
};

int main() {
    using namespace std;
    cout << B1() << endl;
    cout << C1();
    cout << C2() << B2() << endl;
}
Run Code Online (Sandbox Code Playgroud)

输出应为"<[]>".但是,它是"<[]]".

  1. 我错了吗?如果是这样,为什么?
  2. 如果没有,那么这种行为的潜在原因是什么?

NPE*_*NPE 5

实际上,由于以下原因,代码的行为未定义:

return this->operator std::string().c_str();
Run Code Online (Sandbox Code Playgroud)

你正在呼叫c_str()一个临时的,并在以后使用结果.

您所看到的是未定义行为的有效表现.

现在,如果你对引擎盖下实际发生的事情感到好奇,你可以修改最后一行main()来阅读:

    cout << (const void*)C2() << ' ' << (const void*)B2() << endl;
Run Code Online (Sandbox Code Playgroud)

如果你这样做,你可能会看到相同的地址被打印两次(在两种情况下都是悬空指针).这就是我的电脑上发生的事情,我怀疑你的电脑会发生什么.当然,由于行为未定义,这只是许多人的一种可能的表现形式.