#include <iostream> using namespace std; class B { public: void invoke(){ cout << "invoke"; } }; class A{ public: B* test(){ B b; auto *bb = &b; return bb; } }; int main() { A a; B *b = a.test(); b->invoke(); b->invoke(); return 0; } 

A few questions about this code:

  1. will it be correct?
  2. why the compiler does not swear at return bb;
  3. why this code works, because auto * bb is a local variable (stack) and must die with everything together when the method ends (return)
  • one
    And this is the main trouble with c ++, c ++ all allow, as if it should be so, and then again - and ub :). But they make you think) - Alexander

2 answers 2

  1. What is "correct"? Does it contain diagnosable compilation errors? Yes, from this point of view, the code is "correct".

    However, it generates undefined behavior due to the fact that the -> operator performs the indirection of a returned a.test() pointer with an invalid pointer value.

  2. And why should he swear? There are no violations that the compiler is obliged to diagnose (as required by the language specification), in this return bb; not.

    However, it should be remembered that indefinite behavior can be expressed in the refusal of the compiler to compile the program code.

  3. This code does not work. It gives rise to indefinite behavior.

    No, it will not. Although it will work :)

    1. Returning a pointer to a local variable is incorrect.

    2. Probably, the level of warnings is insufficient ... Visual C ++ 2017 with / W4 scolds - "returning the address to a local or temporary variable."

    3. In the invoke() call, the pointer to the object is not used at all, therefore, it is sent to it on a drum, a pointer to that ... Most likely, it will work normally - although not required (UB).

    Like that.

    Correction options:

     B* test() { static B b; return &b; } B* test() { return new B; } 

    The first option is bad because it always returns the same pointer; the second is that then you need to remember to delete the created object. It is better to use an intellectual pointer of the type unique_ptr , which will then destroy it itself.

    • Returning a pointer to a local variable is incorrect. This code does not "work." It gives rise to indefinite behavior. This is solved using new, in the main method do delete b? - TomX01
    • 3
      @ TomX01 What do you mean by "not working"? Formally - yes, I wrote that it is incorrect. In fact - show me at least one compiler that does not print "invoke". Sometimes get down from the heights of the ideal (ie, non-existent) compilers to the sinful earth :) Let us sometimes say how it will be in practice, and not how it should be. If everything was as it was written, we would have lived under communism back in 1981 :) - Harry
    • I realized that this approach is not true. How to correctly return a pointer from a function? Make new and then call delete b in main? - TomX01 8:56 pm
    • @ TomX01 See the amended answer. - Harry
    • one
      @Arhad The function is not virtual, this dereference is not required ... I think that the compiler will simply stick call for a specific address and will not bother about what kind of object it uses. The VC ++ optimizer simply stuck the two outputs of the invoke ... Without the optimizer, stuck the this address into rcx and made the call. The challenge itself is simple invoke output, without attempting dereference ... By the way, it works even when assigning b=nullptr :) - Harry