unique_ptr为具体类型

rra*_*jik 0 c++ pointers object-lifetime undefined-behavior unique-ptr

#include <iostream>
#include <memory>

class Base
{
public:
    virtual void foo() = 0;
};

class Derived : public Base
{
public:
    void foo() override { std::cout << "Derived" << std::endl; }
};

class Concrete
{
public:
    void Bar() { std::cout << "concrete" << std::endl; }
};

int main()
{
    std::unique_ptr<Concrete> ConcretePtr = nullptr;
    ConcretePtr->Bar();
    std::unique_ptr<Base> BasePtr;
    BasePtr->foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我假设将一个unique_ptr声明为具体类型Concrete,为类型的对象分配内存,Concrete而unique_ptr开始指向它.我的假设/理解是否正确?我问,因为ConcretePtr->Bar();打印机"混凝土"到控制台.但是,如果我创建一个指向接口的唯一指针Base,它不知道我需要的确切对象类型,也不知道在内存中分配/获取资源.

这失败BasePtr->foo();BasePtr._Mypair._Myval2 was nullptr.

为什么第一个声明std::unique_ptr<Concrete> ConcretePtr = nullptr;自己分配一个对象?如果我不希望它指向那一行代码中的某个真实对象,但只想要一个智能指针呢?

现在,如果我将声明更改为std::unique_ptr<Concrete> ConcretePtr;以及Concrete类型如下,

class Concrete
{
    int ConcreteNum;
public:
    void Bar() 
    { 
        std::cout << "concrete" << std::endl; 
        ConcreteNum = 38;
        std::cout << ConcreteNum << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

它没有ConcreteNum = 38;抱怨那thisnullptr; 如果这this就是nullptr为什么以及之前的呼叫(哪里Concrete没有任何状态ConcreteNum)如何Bar工作?

而且为什么它不会失败ConcretePtr->Bar();(这->需要一个具体的对象,不是吗?this这里有什么?)但是在内部Bar,在那个任务中?

我也看到同样的问题std::shared_ptr.我不太确定声明,初始化和赋值之间的区别.请帮我理解.

我正在使用MSVC.

Ric*_*ges 5

unique_ptr模型的指针.也就是说,它是指向另一个对象的对象.

初始化unique_ptrwith nullptr会在未指向或拥有另一个对象的状态下创建它.

这就像说Concrete* p = nullptr.

以下列方式之一初始化它:

std::unique_ptr<Concrete> p{new Concrete()};
Run Code Online (Sandbox Code Playgroud)

要么

std::unique_ptr<Concrete> p;  // = nullptr is implied.
p.reset(new Concrete());
Run Code Online (Sandbox Code Playgroud)

或更好:

std::unique_ptr<Concrete> p = std::make_unique<Concrete>();
Run Code Online (Sandbox Code Playgroud)

或者干脆:

auto p = std::make_unique<Concrete>();
Run Code Online (Sandbox Code Playgroud)

但是在这种情况下要小心,如果你真的想要指向Base接口:

std::unique_ptr<Base> p = std::make_unique<Derived>();
Run Code Online (Sandbox Code Playgroud)

要么

std::unique_ptr<Base> p = nullptr;

p = std::make_unique<Derived>();  // assignment from rvalue ref of compatible unique_ptr.
Run Code Online (Sandbox Code Playgroud)