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 开始指向它。我的 assumption/understanding 正确吗?我问是因为 ConcretePtr->Bar();
将 "concrete" 打印到控制台。但是,如果我创建一个指向接口 Base
的唯一指针,它不知道我需要的对象的确切类型,也不知道内存中的 allocate/acquire 资源。
这在 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;
I assume declaring a unique_ptr to a concrete type Concrete, allocates memory for an object of type Concrete and the unique_ptr starts pointing to it. Is my assumption/understanding correct ?
好吧,你可以简单地检查一下。为 Concrete
编写一个默认构造函数,打印出一些东西,这样您就可以知道实例何时创建。 运行 尽可能小的程序(就是上面 main
中的那一行)。您看到预期的输出了吗?
你应该在 提问之前 检查这些东西(并且可能在阅读 documentation 之后),但为了节省你的时间: 否,该行不构造 Concrete
.
类型的对象
您还可以明确检查 unique_ptr
是否正在管理一个对象,使用
if (!ConcretePtr) {
std::cout << "ConcretePtr doesn't point to anything\n";
} else {
std::cout << "ConcretePtr owns an object\n";
}
这项检查也很简单,您可以在提问之前轻松完成。
I ask because ConcretePtr->Bar();
prints "concrete" to the console
这是一个糟糕的测试,因为如果指针 是 一个 nullptr
,这是未定义的行为。如果您关心指针是否是 nullptr
,您应该在 取消引用之前显式检查 ,如上所述。
为了证明为什么这个测试让你感到困惑(你应该优先使用上面的那些),考虑一个可能的非虚拟成员函数的实现(回想一下他们得到一个隐式 this
指针):
// void Concrete::Bar() implemented as
void Concrete_Bar(Concrete *this)
// and ConcretePtr->Bar() implemented as
Concrete_Bar(ConcretePtr.get());
所以,您只是将 nullptr
传递给忽略其唯一参数的函数,而您从未测试过您认为已经完成的事情。
#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 开始指向它。我的 assumption/understanding 正确吗?我问是因为 ConcretePtr->Bar();
将 "concrete" 打印到控制台。但是,如果我创建一个指向接口 Base
的唯一指针,它不知道我需要的对象的确切类型,也不知道内存中的 allocate/acquire 资源。
这在 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;
I assume declaring a unique_ptr to a concrete type Concrete, allocates memory for an object of type Concrete and the unique_ptr starts pointing to it. Is my assumption/understanding correct ?
好吧,你可以简单地检查一下。为 Concrete
编写一个默认构造函数,打印出一些东西,这样您就可以知道实例何时创建。 运行 尽可能小的程序(就是上面 main
中的那一行)。您看到预期的输出了吗?
你应该在 提问之前 检查这些东西(并且可能在阅读 documentation 之后),但为了节省你的时间: 否,该行不构造 Concrete
.
您还可以明确检查 unique_ptr
是否正在管理一个对象,使用
if (!ConcretePtr) {
std::cout << "ConcretePtr doesn't point to anything\n";
} else {
std::cout << "ConcretePtr owns an object\n";
}
这项检查也很简单,您可以在提问之前轻松完成。
I ask because
ConcretePtr->Bar();
prints "concrete" to the console
这是一个糟糕的测试,因为如果指针 是 一个 nullptr
,这是未定义的行为。如果您关心指针是否是 nullptr
,您应该在 取消引用之前显式检查 ,如上所述。
为了证明为什么这个测试让你感到困惑(你应该优先使用上面的那些),考虑一个可能的非虚拟成员函数的实现(回想一下他们得到一个隐式 this
指针):
// void Concrete::Bar() implemented as
void Concrete_Bar(Concrete *this)
// and ConcretePtr->Bar() implemented as
Concrete_Bar(ConcretePtr.get());
所以,您只是将 nullptr
传递给忽略其唯一参数的函数,而您从未测试过您认为已经完成的事情。