将共享指针传递给不同对象中的 stl 容器的正确方法是什么,因此不会提前销毁对象?
我有多个带有 std::queue 的系统:
class System {
typedef std::shared_ptr<Event> EventPtr;
protected:
std::queue<EventPtr> mEventQueue;
static SystemManager * sSystemManager;
//this holds all the systems in the application
public:
System();
~System();
void addEventToQueue(EventPtr event) {
mEventQueue.push(event);
}
void callEventQueue() {
while(!mEventQueue.empty()) {
acceptEvent(mEventQueue.front().get());
mEventQueue.pop();
}
}
void acceptEvent(Event * event);
public:
static void sendEvent(EventPtr &event) {
for(auto system : sSystemManager->getSystems()) {
system->addEventToQueue(event);
}
}
};
Run Code Online (Sandbox Code Playgroud)
我想知道我是否理解正确:
当我调用System::sendEvent(std::make_shared<Event>("testEvent"));作用域时,它将共享指针作为引用传递,该引用不会创建新指针并且不会增加引用计数。但是,addEventToQueue函数将参数作为对象传递,因此引用计数增加;如果我有 5 个系统,引用计数将为 6(计算 std::make_shared 本身)。但是这个引用计数存储在哪里呢?它是通过创建的第一个共享指针std::make_shared吗?还是所有对象的计数相同?那么,当第一个对象超出范围时,其他对象会发生什么?他们怎么知道正确的引用计数是多少,因为他们只知道“父”对象?
我读过的所有关于共享指针的文章,引用计数的显示方式总是很常见的。计数器是静态变量吗?
我已经决定我已经厌倦了决定哪些类负责删除哪些位图.我试图重写我的代码以使用自定义删除器的智能指针al_destroy_bitmap
我的代码非常简单.
shared_ptr<ALLEGRO_BITMAP> test = make_shared<ALLEGRO_BITMAP>(al_load_bitmap("hello.png"), al_destroy_bitmap);
Run Code Online (Sandbox Code Playgroud)
我遇到了一些我似乎无法解决的错误.
error C2079: 'std::_Get_align<ALLEGRO_BITMAP>::Elt2' uses undefined struct 'ALLEGRO_BITMAP'
error C2079: 'std::_Get_align<ALLEGRO_BITMAP>::Elt0' uses undefined struct 'ALLEGRO_BITMAP'
error C2027: use of undefined type 'ALLEGRO_BITMAP'
error C2027: use of undefined type 'ALLEGRO_BITMAP'
Run Code Online (Sandbox Code Playgroud)
解决我的问题的其他解决方案是创建一个Bitmap类来包装所有Allegro的东西,但这看起来很难看,我认为我不应该这样做.另外,我已经到处使用其他的allegro函数,然后我想为ALLEGRO_SAMPLE和编写相同类型的类ALLEGRO_FONT.我真的不喜欢这样做.
如何在Allegro位图中使用智能指针?
编辑:也许为非Allegro编码员提供ALLEGRO_BITMAP如何工作的感觉,我将在下面发布一些代码
ALLEGRO_BITMAP *test = al_load_bitmap("hello.png") // This works
ALLEGRO_BITMAP test1; // This fails with error C2079 undefined struct ALLEGRO_BITMAP. I expect this here.
Run Code Online (Sandbox Code Playgroud) 我有一个类在其构造函数中接收共享指针并将其存储在弱指针中,但我不确定如何(以及在何处)执行此转换.
class A {
public:
A(std::shared_ptr<B> Bptr);
private:
std::weak_ptr<B> m_Bptr;
};
Run Code Online (Sandbox Code Playgroud)
我应该转换shared_ptr之前传递给构造函数吗?
传递shared_ptr到这样weak_ptr的初始化列表是否A(std::shared_ptr<B> Bptr) : m_Bptr(Bptr) { }按预期工作或者我需要在构造函数的主体中显式转换?
从std::unique_ptr<>()的文档中,我不清楚初始化指针时可能会发生什么。
分配时std::shared_ptr<>(),它会分配一个内存缓冲区来处理引用计数器。所以我可能会得到一个std::bad_alloc例外。
初始化唯一指针时会发生类似的事情吗?
我问这个问题是因为如果确实如此,我实际上可能会丢失我试图通过唯一指针删除的内容。例如:
void deleter(FILE * f)
{
fclose(f);
}
void func()
{
...
FILE * f(fopen("/tmp/random", O_CREAT | ...));
if(f == nullptr) ...handle error...
std::unique_ptr<FILE, decltype(&deleter)> raii_file(f, deleter);
...
}
Run Code Online (Sandbox Code Playgroud)
所以,如果初始化unique_ptr<>()可以抛出,我最终可能会f永远保持文件打开。(我FILE *举个例子,任何类似的资源都可能受到影响。)
反对这个答案,我显然不能使用,std::make_unique<>()因为我不只是分配内存。
初始化std::unique_ptr<>()之前的fopen(),然后将值保存在之后会更安全吗?
...
std::unique_ptr<FILE, decltype(&deleter)> raii_file(nullptr, deleter);
FILE * f(fopen("/tmp/random", O_CREAT | ...));
if(f == nullptr) ...handle error...
raii_file = f;
...
Run Code Online (Sandbox Code Playgroud)
或者会不会有类似的问题?
为什么下面的代码不起作用?
class A {};
void f(A* a) {
shared_ptr<A> c(a);
}
int main() {
auto a = make_shared<A>();
auto b = a.get();
f(b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在范围的最后f,我的程序崩溃了.可能是什么导致了这个?有什么东西试图被删除而且不存在吗?
我正在寻找类似于Arc/的智能指针,Rc但它不允许共享所有权。
我想要尽可能多的rc::Weak引用,但我只想要一个强引用,也就是所有者。我想用类型系统来强制执行。
Arc/Rc可以被克隆,它们可以在多个地方拥有。
卷起我自己的智能指针将是一种选择,但我相信这样的数据结构应该已经存在,即使在标准库之外。
我正在寻找一种提供这种接口的数据结构:
impl MySmartPointer<T> {
fn new(object: T) -> Self;
fn weak_ref(&self) -> WeakRef<T>;
fn get_mut(&mut self) -> &mut T;
}
impl WeakRef<T> {
/// If the strong pointer `MySmartPointer` has been dropped,
/// return `None`. Else return Some(&T);
fn get(&self) -> Option<&T>;
}
Run Code Online (Sandbox Code Playgroud) 我将原始指针传递给两个不同的闭包,并将原始指针转换为使用引用Box::from_raw(),程序运行正常。
但是,在将原始指针转换为引用后,析构函数应自动调用,如文档所述:
这个函数是不安全的,因为使用不当可能会导致内存问题。例如,如果函数在同一个原始指针上被调用两次,则可能会发生双重释放。
但是,即使在Box::from_raw()两次调用原始指针之后,我也能够访问对 ABC 的引用,并且它工作正常。
struct ABC {}
impl ABC {
pub fn new() -> ABC {
ABC {}
}
pub fn print(&self, x: u32) {
println!("Inside handle {}", x);
}
}
fn main() {
let obj = ABC::new();
let const_obj: *const ABC = &obj;
let handle = |x| {
let abc = unsafe { Box::from_raw(const_obj as *mut ABC) };
abc.print(x);
};
handle(1);
let handle1 = |x| {
let abc = unsafe { Box::from_raw(const_obj as …Run Code Online (Sandbox Code Playgroud) 我注意到这可以编译:
#include<memory>
#include<iostream>
using namespace std;
int main()
{
unique_ptr<int>a(nullptr);
if(!a)
cout<<"NULLPTR";
}
Run Code Online (Sandbox Code Playgroud)
但是,这不是:
#include<memory>
#include<iostream>
using namespace std;
int main()
{
unique_ptr<int>a(NULL);
if(!a)
cout<<"NULL";
}
Run Code Online (Sandbox Code Playgroud)
我正在使用具有多个函数的库,这些函数返回原始指针,并且使用后必须手动释放它们。我想使用unique_ptr(带有自定义删除器)来管理这样的原始指针。我担心那些函数返回NULL的情况,因为我认为这可能会引起一些问题。
我有一个类,其对象指针将作为键/数据添加到多个 std::map/std::unordered_map/hash(内部实现)中。为了自动删除对象,我使用了 shared_ptr。
我使用shared_ptr only类设计了我的类。
现在我想确保将来没有人这样做:
#include <memory>
#include <string>
class A {
protected:
struct this_is_private;
public:
explicit A(const this_is_private &) {}
A(const this_is_private &, ::std::string, int) {}
template <typename... T>
static ::std::shared_ptr<A> create(T &&...args) {
return ::std::make_shared<A>(this_is_private{0},
::std::forward<T>(args)...);
}
protected:
struct this_is_private {
explicit this_is_private(int) {}
};
A(const A &) = delete;
const A &operator =(const A &) = delete;
};
::std::map<A*, int> m_error;
::std::map<::std::shared_ptr<A>, int> m_ok;
::std::shared_ptr<A> foo()
{
::std::shared_ptr<A> temp = A::create();
A * obj_ptr …Run Code Online (Sandbox Code Playgroud) std::vector<unique_ptr<int>> v;
v.push_back(std::make_unique<int>(1));
unique_ptr<int>& rp0 = v[0];
cout << "rp1="<<rp0.get()<<"\n";
cout << "*rp1="<<*rp0<<"\n";
v.push_back(std::make_unique<int>(2));
cout << "rp1="<<rp0.get()<<"\n";
cout << "*rp1="<<*rp0<<"\n";
Run Code Online (Sandbox Code Playgroud)
为什么第二张打印结果与第一张打印结果不同?
rp1=0x1783c20
*rp1=1
rp1=0
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)