有没有办法防止自动变量被删除?

时间:2016-11-12 05:11:16

标签: c++ scope

我知道甚至只是为了记录而考虑非常糟糕:我并不是想在任何严肃的应用程序中使用它,所以请尝试回答问题而不是指出它有多不合适。

我正在努力完成的例子:

def __init__(self, canvas, color):  # <--- double underscores
    self.canvas = canvas
    self.id = canvas.create_oval(0, 0, 100, 100)  # <--- missing arguments
    self.canvas.move(self.id, 245, 100)

编辑:唯一的要求是主要功能不应该改变。

我意识到有些事情根本不可能,所以如果就是这种情况我就不会哭。出于好奇,我想到了这个问题。

5 个答案:

答案 0 :(得分:3)

抱歉,但这是不可能的。一旦堆栈上的对象超出范围,您的指针就会无效。

答案 1 :(得分:2)

Don't try this at home but you could probably achieve something like this using a reference counted PIMPL and an overloaded operator&:

class ExampleImpl {
public:
    ExampleImpl() {
        std::cout << "constructor called" << std::endl;
    }
    ~ExampleImpl() {
        std::cout << "destructor called" << std::endl;
    }
};

class Example {
    std::shared_ptr<ExampleImpl> impl;
public:
    Example() : impl(std::make_shared<ExampleImpl>()){}
    Example* operator&() { return new Example(*this); }
};

Live demo.

答案 2 :(得分:1)

Firstly, you are using the wrong syntax to explicitly call an destructor (delete both calls the destructor and deallocates the memory storing the object); you want:

int main() {
    Example* example_pointer;

    {
        Example example; // prints "constructor called"
        example_pointer = &example;
    } // example still exists here, nothing is printed

    example_pointer->~Example(); // deleting automatic variable manually
    // Prints "destructor called"
}

That said, what you want is not possible. When an automatic variable goes out of scope, it will always be destroyed. The closest you could get would be to manually construct the Example object in stack memory that had been allocated earlier in main:

int main() {
    alignas(Example) char example_storage[sizeof (Example)];
    Example* example_pointer;

    {
        Example &example = *new (&example_storage) Example; // prints "constructor called"
        example_pointer = &example;
    } //nothing is printed; `example` is only a reference,
      //so when it goes out of scope no destruction happens

    example_pointer->~Example(); // deleting automatic variable manually
                                 // Prints "destructor called"
}

答案 3 :(得分:1)

The closest way would be to use a technique that explicitly disrespects scope. There is one well-known way in C++ to make a change that disrespects scope, and that is to use the preprocessor.

A simple

#define Example static Example

after the class definition and before main() would have the required effect.

The only limitation is that the delete example_pointer would have undefined behaviour, and that the destructor would probably be invoked after main() returns (not before the return statement in main()).

Technically, this does actually change the main() function, since it alters the code seen in phases of compilation post preprocessing.

If you remove the delete example_pointer, all requirements except the last are met.

答案 4 :(得分:1)

任何人都没有想到的一种方法是jmping out of function而不是返回。也就是说,使用内联汇编,内在函数或longjmp()。这样就不会更新堆栈指针,也不会调用析构函数,堆栈将保持不变。

实施例

#include <csetjmp>

#include <iostream>

jmp_buf buf;

int const* p;

[[noreturn]] void f() noexcept
{
  int const a(666);

  p = &a;

  longjmp(buf, 1);
}

int main()
{
  if (setjmp(buf))
  {
    auto const t(*p);

    ::std::cout << t << ::std::endl;
  }
  else
  {
    f();
  }

  return 0;
}