#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;
}
我假设将unique_ptr声明为具体类型Concrete
,为类型为Concrete
的对象分配内存,而unique_ptr开始指向它。我的假设/理解是否正确?我问,因为ConcretePtr->Bar();
打印&#34;具体&#34;到控制台。但是,如果我创建一个指向接口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;
}
};
在ConcreteNum = 38;
抱怨this
为nullptr
时失败了;如果此this
为nullptr
,那么为什么以及之前的调用(Concrete
哪个州没有ConcreteNum
}到Bar
工作的原因是什么?
此外,为什么它不会在ConcretePtr->Bar();
失败(这个->
需要一个具体的对象,不是吗?这里的this
是什么?)但是在Bar
里面,那个任务?
我也看到std::shared_ptr
同样的问题。我不太确定声明,初始化和放大之间的区别。分配。请帮我理解。
我正在使用MSVC。
答案 0 :(得分:5)
unique_ptr
为指针建模。也就是说,它是指向另一个对象的对象。
使用nullptr初始化unique_ptr
会在未指向或拥有另一个对象的状态下创建它。
这就像说Concrete* p = nullptr
。
以下列方式之一对其进行初始化:
std::unique_ptr<Concrete> p{new Concrete()};
或
std::unique_ptr<Concrete> p; // = nullptr is implied.
p.reset(new Concrete());
或者,更好:
std::unique_ptr<Concrete> p = std::make_unique<Concrete>();
或简单地说:
auto p = std::make_unique<Concrete>();
但是在这种情况下要小心,如果你真的想要指向Base接口:
std::unique_ptr<Base> p = std::make_unique<Derived>();
或
std::unique_ptr<Base> p = nullptr;
p = std::make_unique<Derived>(); // assignment from rvalue ref of compatible unique_ptr.
答案 1 :(得分:3)
brew services stop
我假设将一个unique_ptr声明为具体类型Concrete,为Concrete类型的对象分配内存,而unique_ptr开始指向它。我的假设/理解是否正确?
嗯,你可以轻松检查。为 std::unique_ptr<Concrete> ConcretePtr = nullptr;
编写一个默认构造函数,用于打印出一些内容,以便您可以确定何时创建实例。运行尽可能小的程序(只是Concrete
中的上一行)。你看到了预期的产量吗?
您应该在提出问题之前检查这些内容(可能在阅读documentation之后),但为了节省您的时间:否,该行不构造main
类型的对象。
您还可以使用
明确检查Concrete
是否正在管理对象
unique_ptr
这项检查也很简单,你可以在提问之前轻松完成。
我问,因为
if (!ConcretePtr) { std::cout << "ConcretePtr doesn't point to anything\n"; } else { std::cout << "ConcretePtr owns an object\n"; }
打印&#34;具体&#34;到控制台
这是一个糟糕的测试,因为如果指针 是ConcretePtr->Bar();
,那么它是未定义的行为。如果您关心指针是否为nullptr
,则应在解除引用之前明确检查,如上所述。
为了演示为什么这个测试让你感到困惑(你应该优先使用上面的那个),考虑非虚拟成员函数的可能实现(回想一下他们得到一个隐含的{{1} }指针):
nullptr
所以,你刚刚将一个this
传递给一个忽略其唯一参数的函数,而你从未测试过你认为你做过的事情。