C++ 独特的_ptr<;T>;。使用原始指针赋值时get()方法调用析构函数?
下面的程序使用C++ 独特的_ptr<;T>;。使用原始指针赋值时get()方法调用析构函数?,c++,pointers,c++11,crash,unique-ptr,C++,Pointers,C++11,Crash,Unique Ptr,下面的程序使用std::unique_ptr来避免手动内存管理。我尝试了两种方法来实现它。问题在于第二种方法,在分配给原始指针之前,调用析构函数。当以后的代码试图访问无效内存时,这会导致程序崩溃 我在第二种方法中的意图是,如何使用具有现有代码库的智能指针,以便我可以利用智能指针提供的自动内存管理。因此,我没有更改声明中指针的类型(.e.从Widget*w到std::unique_ptr w) 有人能详细解释一下吗?最好的做法是什么?。或者我错过了什么 #include<iostream&g
std::unique_ptr
来避免手动内存管理。我尝试了两种方法来实现它。问题在于第二种方法,在分配给原始指针之前,调用析构函数。当以后的代码试图访问无效内存时,这会导致程序崩溃
我在第二种方法中的意图是,如何使用具有现有代码库的智能指针,以便我可以利用智能指针提供的自动内存管理。因此,我没有更改声明中指针的类型(.e.从Widget*w
到std::unique_ptr w
)
有人能详细解释一下吗?最好的做法是什么?。或者我错过了什么
#include<iostream>
#include<memory>
class Widget {
public:
Widget() { std::cout << "Widget::Widget()" << std::endl; }
virtual ~Widget() { std::cout << "Widget::~Widget()" << std::endl; }
virtual void draw() = 0;
};
class WindowsButton : public Widget {
public:
WindowsButton() = default;
~WindowsButton() = default;
void draw() { std::cout << "WindowsButton"<<std::endl; }
};
int main() {
// Working Code
// std::unique_ptr<Widget> w = std::unique_ptr<Widget>(new WindowsButton());
// w.get()->draw();
//In this way program is crashing while calling the w->draw()
Widget* w = std::unique_ptr<Widget>(new WindowsButton()).get();
w->draw();
}
#包括
#包括
类小部件{
公众:
Widget(){std::cout在第二种情况下,您正在创建一个unique\u ptr
的临时实例,并在其上调用get()
成员函数。unique\u ptr
对象将在完整表达式的末尾(分号处)被销毁
然后将取消引用指向无效内存位置的指针,从而导致未定义的行为。在第二种情况下,您正在创建一个unique\u ptr
的临时实例,并对其调用get()
成员函数。unique\u ptr
对象将在完整表达式结束时销毁(在分号处)
然后将取消引用指向无效内存位置的指针,从而导致未定义的行为。在这一行中
Widget* w = std::unique_ptr<Widget>(new WindowsButton()).get();
当时,w
是一个悬空的指针。在这行中
Widget* w = std::unique_ptr<Widget>(new WindowsButton()).get();
那时,w
是一个悬而未决的指针。也许你误解了一点unique\u ptr
。它不是帮助管理原始指针的内存,而是替换原始指针。在这两个示例中,你都返回到调用get()
在unique\u ptr
上获取原始指针并使用它。这是不需要的。您可以使用unique\u ptr
完成所有使用原始指针的操作,除了复制它并调用delete
您在第二个示例中遇到的问题是生存期问题。由于unique\u ptr
拥有它指向的对象,因此它控制其生存期,这意味着当unique\u ptr
被销毁时,该对象必须被销毁。由于unique\u ptr
是一个临时对象,因此它会在同一行中销毁该对象
因此,临时的unique\u ptr
s几乎没有什么用处,除非您使用它们初始化另一个unique\u ptr
、共享的\u ptr
或其他接管所有权的对象,从而使unique\u ptr
为空
在以下几行中,我将稍微润色一下您的“工作代码”:
这是C++03风格的使用方法,C++11也可以。人们对如何以及何时使用C++11功能(如auto
和统一初始化)给出了不同的建议,因此下面是一些在C++11中也会很好/更好的示例:
std::unique_ptr<Widget> w{new WindowsButton{}};
在这里,w
有类型std::unique\u ptr
,但这通常不会有什么影响,因为如果需要,它可以转换为std::unique\u ptr
。可能您误解了一点unique\u ptr
。这不是帮助原始指针的内存管理的方法,而是替换原始指针。在两个示例中返回到对unique\u ptr
调用get()
,以获取原始指针并使用它。这不是必需的。您可以使用unique\u ptr
执行原始指针的所有操作,除了复制和调用delete
您在第二个示例中遇到的问题是生存期问题。由于unique\u ptr
拥有它指向的对象,因此它控制其生存期,这意味着当unique\u ptr
被销毁时,该对象必须被销毁。由于unique\u ptr
是一个临时对象,因此它会在同一行中销毁该对象
因此,临时的unique\u ptr
s几乎没有什么用处,除非您使用它们初始化另一个unique\u ptr
、共享的\u ptr
或其他接管所有权的对象,从而使unique\u ptr
为空
在以下几行中,我将稍微润色一下您的“工作代码”:
这是C++03风格的使用方法,C++11也可以。人们对如何以及何时使用C++11功能(如auto
和统一初始化)给出了不同的建议,因此下面是一些在C++11中也会很好/更好的示例:
std::unique_ptr<Widget> w{new WindowsButton{}};
在这里,w
有类型std::unique_ptr
,但这通常不会有什么伤害,因为如果需要,它可以转换为std::unique_ptr
。简单地制作w
astd::unique_ptr
,有什么问题吗?@0x499602D2:更改原型没有问题。但正如我在文章中提到的那样,所以我想要在第一种情况下,unique_ptr
提供了一个操作符->()
重载,因此w->draw();
可以工作。您必须构造一个std::unique_ptr
然后调用get())
简单地制作w
astd::unique_ptr
有什么问题?@0x499602D2:更改原型没有问题。但是正如我在中提到的,我想在现有的代码库中做这件事。不需要w.get()->draw()
在第一种情况下,unique\u ptr
提供了一个操作符->()
重载,因此w->draw();
可以工作。您必须构造一个std::unique\u ptr
然后调用get()
std::unique_ptr<Widget> w = std::unique_ptr<Widget>(new WindowsButton());
w.get()->draw();
std::unique_ptr<Widget> w(new WindowsButton());
w->draw();
std::unique_ptr<Widget> w{new WindowsButton{}};
auto w{std::unique_ptr<Widget>{new WindowsButton{}}};
auto w{std::make_unique<WindowsButton>()};