我和其他许多人一样,使用智能指针在C++中包含不安全的内存操作,使用RAII等等,已经取得了巨大的成功.但是,当您具有析构函数,类,运算符重载等时,包装内存管理更容易实现.
对于使用原始C99编写的人,您可以在哪里指出(没有双关语)来帮助安全内存管理?
谢谢.
有什么区别:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
Run Code Online (Sandbox Code Playgroud)
和
std::shared_ptr<int> p = std::make_shared< int >();
Run Code Online (Sandbox Code Playgroud)
?
我应该选择哪一个?为什么?
PS相当肯定这已经得到了答案,但我找不到类似的问题.
std::observer_ptr
库基础技术规范V2 中的构造究竟有什么意义?
在我看来,它所做的一切都是裸露的T*
,如果不增加动态内存安全性,这似乎是一个多余的步骤.
在我的所有代码中,我使用std::unique_ptr
了我需要明确拥有对象的位置以及std::shared_ptr
可以共享对象所有权的位置.
这非常有效并且可以防止意外解除引用已经被破坏的对象.
std::observer_ptr
当然,不保证观察到的物体的寿命.
如果它是从a构造的,std::unique_ptr
或者std::shared_ptr
我会看到在这样的结构中使用,但任何简单使用的代码T*
可能只是继续这样做,如果他们计划移动到任何它将是std::shared_ptr
和/或std::unique_ptr
(取决于在使用上).
给出一个简单的示例函数:
template<typename T>
auto func(std::observer_ptr<T> ptr){}
Run Code Online (Sandbox Code Playgroud)
如果停止智能指针在观察它们时销毁它们存储的对象将会有用.
但如果我想观察std::shared_ptr
或std::unique_ptr
我必须写:
auto main() -> int{
auto uptr = std::make_unique<int>(5);
auto sptr = std::make_shared<int>(6);
func(uptr.get());
func(sptr.get());
}
Run Code Online (Sandbox Code Playgroud)
这使得它不比以下更安全:
template<typename T>
auto func(T *ptr){}
Run Code Online (Sandbox Code Playgroud)
那么,这个新结构的用途是什么?
它只是用于自我记录的来源吗?
5 规则指出,如果一个类有一个用户声明的析构函数、复制构造函数、复制赋值构造函数、移动构造函数或移动赋值构造函数,那么它必须有其他 4 个。
但今天我突然明白了:你什么时候需要用户定义的析构函数、复制构造函数、复制赋值构造函数、移动构造函数或移动赋值构造函数?
在我的理解中,隐式构造函数/析构函数适用于聚合数据结构。但是,管理资源的类需要用户定义的构造函数/析构函数。
但是,不能将所有资源管理类都使用智能指针转换为聚合数据结构吗?
例子:
// RAII Class which allocates memory on the heap.
class ResourceManager {
Resource* resource;
ResourceManager() {resource = new Resource;}
// In this class you need all the destructors/ copy ctor/ move ctor etc...
// I haven't written them as they are trivial to implement
};
Run Code Online (Sandbox Code Playgroud)
对比
class ResourceManager {
std::unique_ptr<Resource> resource;
};
Run Code Online (Sandbox Code Playgroud)
现在示例 2 的行为与示例 1 完全相同,但所有隐式构造函数都可以工作。
当然,你不能 copy ResourceManager
,但如果你想要不同的行为,你可以使用不同的智能指针。
关键是当智能指针已经有那些隐式构造函数可以工作时,你不需要用户定义的构造函数。
我认为拥有用户定义的构造函数的唯一原因是:
你不能在一些低级代码中使用智能指针(我非常怀疑这种情况)。
您正在自己实现智能指针。
但是,在普通代码中,我看不出有任何理由使用用户定义的构造函数。
我在这里错过了什么吗?
从C++ 11开始,由于几个原因,开发人员倾向于将智能指针类用于动态生命周期对象.而对于那些新的智能指针类,标准,甚至建议不使用运营商,new
而是建议使用make_shared
或make_unique
避免一些容易出错.
如果我们喜欢使用智能指针类shared_ptr
,我们可以构建一个类似的,
shared_ptr<int> p(new int(12));
Run Code Online (Sandbox Code Playgroud)
我们还希望将自定义删除器传递给智能指针类,
shared_ptr<int> p(new int(12), deleter);
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我们喜欢使用make_shared
分配,例如.int
,而不是使用new
和shared_ptr
构造函数,就像上面的第一个表达式,我们可以使用
auto ip = make_shared<int>(12);
Run Code Online (Sandbox Code Playgroud)
但是,如果我们也希望将自定义删除器传递给make_shared
,那么有没有正确的方法呢?好像编译器,至少gcc,给出错误,
auto ip = make_shared<int>(12, deleter);
Run Code Online (Sandbox Code Playgroud) 我总是认为std::unique_ptr
与使用原始指针相比没有任何开销.但是,编译以下代码
#include <memory>
void raw_pointer() {
int* p = new int[100];
delete[] p;
}
void smart_pointer() {
auto p = std::make_unique<int[]>(100);
}
Run Code Online (Sandbox Code Playgroud)
with g++ -std=c++14 -O3
生成以下程序集:
raw_pointer():
sub rsp, 8
mov edi, 400
call operator new[](unsigned long)
add rsp, 8
mov rdi, rax
jmp operator delete[](void*)
smart_pointer():
sub rsp, 8
mov edi, 400
call operator new[](unsigned long)
lea rdi, [rax+8]
mov rcx, rax
mov QWORD PTR [rax], 0
mov QWORD PTR [rax+392], 0
mov rdx, rax
xor …
Run Code Online (Sandbox Code Playgroud) 关于智能指针和新的C++ 11/14功能,我想知道具有这些功能的类的最佳实践返回值和函数参数类型是什么:
一个工厂函数(在类之外),它创建对象并将它们返回给类的用户.(例如,打开文档并返回可用于访问内容的对象.)
实用程序函数接受来自工厂函数的对象,使用它们,但不取得所有权.(例如,计算文档中单词数量的函数.)
在返回对象后保持对对象引用的函数(如获取对象副本的UI组件,以便它可以根据需要在屏幕上绘制内容.)
工厂功能的最佳返回类型是什么?
delete
正确地使用它,这是有问题的.unique_ptr<>
则用户无法共享它.shared_ptr<>
那么我将不得不传遍各地的shared_ptr<>
类型?这就是我现在正在做的事情,它导致了问题,因为我正在获取循环引用,防止对象被自动销毁.效用函数的最佳参数类型是什么?
const
参数来说明该函数不会修改对象,而不会破坏智能指针的兼容性?保持对象引用的函数的最佳参数类型是什么?
shared_ptr<>
是这里唯一的选择,这可能意味着工厂类必须返回一个shared_ptr<>
,对吗?这里有一些代码可以编译并希望说明要点.
#include <iostream>
#include <memory>
struct Document {
std::string content;
};
struct UI {
std::shared_ptr<Document> doc;
// This function is not copying the object, but holding a
// reference to it to make sure it doesn't get destroyed.
void setDocument(std::shared_ptr<Document> newDoc) {
this->doc = newDoc;
}
void redraw() {
// …
Run Code Online (Sandbox Code Playgroud) 我已经使用了几年的指针,但我最近才决定转换到C++ 11的智能指针(即唯一,共享和弱).我对它们做了很多研究,这些是我得出的结论:
因此,考虑到这些原则,我开始修改我的代码库以利用我们新的闪亮智能指针,完全打算清除尽可能多的原始指针.然而,我对如何最好地利用C++ 11智能指针感到困惑.
例如,让我们假设我们正在设计一个简单的游戏.我们认为将虚构的Texture数据类型加载到TextureManager类中是最佳的.这些纹理很复杂,因此按值传递它们是不可行的.此外,让我们假设游戏对象需要特定的纹理,具体取决于它们的对象类型(即汽车,船等).
之前,我会将纹理加载到矢量(或其他容器,如unordered_map)中,并在每个相应的游戏对象中存储指向这些纹理的指针,以便在需要渲染时可以引用它们.让我们假设纹理保证比指针寿命更长.
那么,我的问题是如何在这种情况下最好地利用智能指针.我看到几个选项:
将纹理直接存储在容器中,然后在每个游戏对象中构造unique_ptr.
class TextureManager {
public:
const Texture& texture(const std::string& key) const
{ return textures_.at(key); }
private:
std::unordered_map<std::string, Texture> textures_;
};
class GameObject {
public:
void set_texture(const Texture& texture)
{ texture_ = std::unique_ptr<Texture>(new Texture(texture)); }
private:
std::unique_ptr<Texture> texture_;
};
Run Code Online (Sandbox Code Playgroud)
然而,我对此的理解是,新的纹理将从传递的引用中复制构造,然后由unique_ptr拥有.这让我觉得非常不受欢迎,因为我会使用与使用它的游戏对象一样多的纹理副本 - 击败指针点(没有双关语意).
不直接存储纹理,而是存储容器中的共享指针.使用make_shared初始化共享指针.构造游戏对象中的弱指针.
class TextureManager {
public:
const std::shared_ptr<Texture>& texture(const std::string& key) const
{ return textures_.at(key); }
private:
std::unordered_map<std::string, std::shared_ptr<Texture>> textures_;
};
class GameObject {
public:
void set_texture(const std::shared_ptr<Texture>& …
Run Code Online (Sandbox Code Playgroud)scoped_ptr
不能复制,并且正在删除范围之外.所以它有点受限制shared_ptr
.因此,除了您真正需要限制复制操作的情况之外,shared_ptr
最好使用.因为有时您不知道需要创建对象的副本或不需要.所以问题是:除了上面提到的情况之外,我们shared_ptr
是否可以考虑使用更好(或推荐)代替scoped_ptr
.是否scoped_ptr
更快地工作shared_ptr
,或者它有什么优势?
谢谢!
C++ 11有相同的东西boost::intrusive_ptr
吗?
我的问题是我的C++代码有一个C风格的界面.接口的两端都可以使用C++,但出于兼容性原因需要公开C接口.我无法使用,std::shared_ptr
因为我必须通过两个(或更多)智能指针来管理对象.我无法找到类似的解决方案boost::intrusive_ptr
.
smart-pointers ×10
c++ ×9
c++11 ×5
shared-ptr ×4
boost ×2
pointers ×2
assembly ×1
c ×1
c++17 ×1
c99 ×1
make-shared ×1
memory ×1
raii ×1
scoped-ptr ×1