unique_ptr到混凝土类型
unique_ptr to a concrete type
#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();
将"混凝土"打印到控制台。但是,如果我创建一个指向接口的唯一指针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。
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.
std::unique_ptr<Concrete> ConcretePtr = nullptr;
我假设声明一个具体类型 Concrete 的unique_ptr,为类型为 Concrete 的对象分配内存,并且unique_ptr开始指向它。我的假设/理解是否正确?
好吧,你可以简单地检查一下。为Concrete
编写一个默认构造函数,用于打印某些内容,以便您可以知道何时创建实例。运行尽可能小的程序(就在上面main
行)。您看到预期的输出了吗?
您应该在提出问题之前(可能在阅读文档之后)检查这些内容,但为了节省时间:不,该行不会构造类型Concrete
的对象。
您还可以显式检查unique_ptr
是否正在管理对象,使用
if (!ConcretePtr) {
std::cout << "ConcretePtr doesn't point to anythingn";
} else {
std::cout << "ConcretePtr owns an objectn";
}
这个检查也是微不足道的,你可以在问问题之前轻松完成。
我问是因为
ConcretePtr->Bar();
将"具体"打印到控制台
这是一个糟糕的测试,因为如果指针是nullptr
,则它是未定义的行为。如果你关心指针是否是nullptr
,你应该在取消引用它之前明确检查它,如上所述。
为了说明为什么这个测试会让你感到困惑(你应该优先使用上面的那些),考虑一个非虚拟成员函数的可能实现(回想一下,它们得到了一个隐式的this
指针):
// void Concrete::Bar() implemented as
void Concrete_Bar(Concrete *this)
// and ConcretePtr->Bar() implemented as
Concrete_Bar(ConcretePtr.get());
因此,您只是将nullptr
传递给忽略其唯一参数的函数,并且您从未测试过您认为您所做的事情。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 在此示例中,基本模板类如何确定第二个混凝土类型
- unique_ptr到混凝土类型
- 混凝土类型的通用参考