C++ 使用std::auto_ptr的意义

C++ 使用std::auto_ptr的意义,c++,pointers,smart-pointers,auto-ptr,C++,Pointers,Smart Pointers,Auto Ptr,什么是auto_ptr? 请看以下代码: #include <iostream> #include <memory> class A { public: ~A() { std::cout << "DEST"; }; }; void func(A* pa) { std::cout << "A pointer"; } void test() { A a; std::auto_ptr&

什么是
auto_ptr
? 请看以下代码:

#include <iostream>
#include <memory>

class A
{
public:
    ~A()
    {
        std::cout << "DEST";
    };
};

void func(A* pa)
{
    std::cout << "A pointer";
}

void test()
{
    A a;
    std::auto_ptr<A> pA(new A);
    //func(pA);  //compiler error here cannot convert parameter 1 from 'std::auto_ptr<_Ty>' to 'A *' 
    std::cout << "end";
}

int main(int argc, char* argv[])
{
    test();
    return 0;
}
#包括
#包括
甲级
{
公众:
~A()
{

std::cout如果您能够在堆栈上创建所有对象,那么就不需要使用
auto_ptr

  • 从函数返回对象(不能返回本地对象)
  • 确保从函数返回的对象要么被调用方接收,要么在出现异常时被销毁
  • 聚合指向类内对象的指针(您需要确保析构函数将其删除,或者只需将其设置为防止内存泄漏的
    自动\u ptr
    ,句号)
  • ……还有更多

再想一想,你可能应该这样做。他知道的比我多。-

这是正确的做法:

void test()
{
    A a;
    std::auto_ptr<A> pA(new A);
    func(pA.get());
    std::cout << "end";
}
void测试()
{
A A;
标准:自动ptr pA(新A);
func(pA.get());
标准::cout
唯一的想法是我不必写删除

是的,考虑到内存泄漏是您将遇到的最常见的错误之一,这是一个相当大的好处

指针的意义是什么?当我离开作用域时,它是否会被破坏。我使用指针来控制变量的活动

你改变了这种想法,用作用域来定义变量的寿命。你只需在适当的作用域中声明这些东西,就不必再担心清理问题了。这就是关键所在

您的示例是精心设计的,但您仍然可以看到它的价值所在。当然,您可能不会忘记在一个完全不起作用的两行函数中调用
delete
。在实际应用程序中,事情会变得更加复杂

<> >当你<代码>新< /代码>一堆对象时,你可以依赖于一个事实:当函数退出时,对象将被清理。类也一样。当一个实例超出范围时,你可以依靠它的析构函数来为你分配内存。考虑在抛出异常时会发生什么。r您需要确保处理每一个可能的异常和每一个可能的返回路径,以确保您自己完成清理

还有

普通变量initialize位于堆栈上,指针位于堆上

不完全正确。本例中的指针具有自动存储持续时间,但它所指向的没有

编译器对您传递
auto\u ptr
发出吠声的原因是函数没有采用
auto\u ptr
。您需要调用
get()
来传递指针本身


<>你说,你不应该使用<代码> AutoPPTR <代码>;如果你有一个C++的0x编译器,你应该使用它。

< P>有很多理由使用<代码> AutoPyTrp>代码>(或其他智能指针)来管理内存。
void test()
{
    A a;
    std::auto_ptr<A> pA(new A);
    if(SomeFunc())
      return;
    //func(pA);  //compiler error here cannot convert parameter 1 from 'std::auto_ptr<_Ty>' to 'A *' 
    std::cout << "end";
}
pA
对象仍然拥有内存;
func
不能删除它,也不能存储它。

重要信息 请记住,
std::auto_ptr
有许多缺点,如果编译器提供,通常应该使用
std::unique_ptr
。(如果没有,请更新编译器!)

现在回到你的问题


使用这个auto_ptr有什么意义?当它作为普通的类初始化变量(a)离开作用域时,它调用类析构函数

没错。
auto_ptr
的原因是强制执行严格的所有权语义,这样当指针本身被销毁时,对象就被正确地销毁了

我无法将此指针传递给具有类指针(func)的函数

可以,您需要使用
get()
来查找原始指针。将指针传递到函数调用时使用
get()
意味着函数不会拥有该对象的所有权(该
auto_ptr
仍然拥有该对象,并期望该对象在函数返回后仍然有效)

或者,您可以在指针上使用
release()
,以获取原始指针,并指示
auto_ptr
不再负责对象的所有权

我不能对[]或char[]使用指针auto_ptr,因为auto_ptr调用delete not delete[]

是的,这是一个问题。这就是为什么自从引入了
独特的ptr
后不再使用
自动ptr
的原因之一。它做同样的事情,但更安全(=更容易)使用,更通用

唯一的想法是我不必写delete,但是如果指针在我超出范围时被破坏,它的意义又是什么呢

这样您就不会忘记它:-)或者您可以使用
auto\u ptr
(或者更好的
unique\u ptr
作为类对象中的成员)

但是,请告诉我使用auto_ptr而不是普通指针的意义是什么

长话短说:许多指针可以指向单个对象。存在各种智能指针,它们使用类型系统记账,由哪个指针拥有对象(=负责释放对象)。


旁注 如果您有一个类(可能)拥有另一个对象的实例,只需编写:

class X {
    // ...
    X() : ptr(new Type()) {}
    X(Type ptr) : ptr(ptr) {}
    // ...
    void setPtr(Type ptr2) { ptr.reset(ptr); }
    // ...
    std::unique_ptr<Type> ptr;
};
<>同样的行为?不!因为现在有了安全的C++代码,当代码< > x>代码>被破坏时,你还需要编写一个析构函数来删除<代码> PTR < /代码>。 现在好了吗?不!因为您有一个公共析构函数,所以需要上卷(或阻止)您自己的复制构造函数和赋值运算符,因为否则您可能会得到两个指向同一类型对象的X实例,而这两个实例在这里都认为自己拥有此实例,并且有时都会尝试删除它。Boom,access违例

Unique_ptr不允许您隐式复制X对象以及对
ptr
的强引用,因为Unique_ptr是不可复制的(它认为它是
class X {
    // ...
    X() : ptr(new Type()) {}
    X(Type ptr) : ptr(ptr) {}
    // ...
    void setPtr(Type ptr2) { ptr.reset(ptr); }
    // ...
    std::unique_ptr<Type> ptr;
};
class X {
   // ...
   X() : ptr(new Type()) {}
   X(Type ptr) : ptr(ptr) {}
   // ...
   void setPtr(Type ptr2) {delete ptr; ptr = ptr2;}
   // ...
   Type* ptr;
};