有没有找到shared_ptr的循环引用的提示/技巧?
这是我想要找到的例子 - 不幸的是我似乎无法在我的代码中找到循环.
struct A
{
boost::shared_ptr<C> anC;
};
struct B
{
boost::shared_ptr<A> anA;
};
struct C
{
boost::shared_ptr<B> anB;
};
Run Code Online (Sandbox Code Playgroud) 我最近开始为自己调查Qt并提出以下问题:
假设我有一些QTreeWidget* widget.在某些时刻,我想添加一些项目,这是通过以下调用完成的:
QList<QTreeWidgetItem*> items;
// Prepare the items
QTreeWidgetItem* item1 = new QTreeWidgetItem(...);
QTreeWidgetItem* item2 = new QTreeWidgetItem(...);
items.append(item1);
items.append(item2);
widget->addTopLevelItems(items);
Run Code Online (Sandbox Code Playgroud)
到目前为止它看起来还不错,但我实际上并不了解谁应该控制对象的生命周期.我应该用一个例子解释一下:
让我们说,另一个函数调用widget->clear();.我不知道这个调用下面会发生什么,但我确实认为,内存分配item1和item2没有得到安置在这里,因为他们的OWNAGE实际上并没有转移.而且,砰的一声,我们有内存泄漏.
问题如下 - 确实Qt可以为这种情况提供一些东西吗?我可以使用boost::shared_ptr或任何其他智能指针,并写出类似的东西
shared_ptr<QTreeWidgetItem> ptr(new QTreeWidgetItem(...));
items.append(ptr.get());
Run Code Online (Sandbox Code Playgroud)
但我不知道Qt本身是否会尝试delete对我的指针进行显式调用(因为我将它们声明为shared_ptr管理状态,这将是灾难性的).
你会如何解决这个问题?也许一切都很明显,我想念一些非常简单的东西?
在make_shared的boost文档中,它说:
除了方便和风格之外,这样的函数也是异常安全且相当快的,因为它可以对对象及其相应的控制块使用单个分配,从而消除了shared_ptr的构造开销的很大一部分.
我不明白"单一分配"的含义,这是什么意思?
如果我move shared_ptr'进shared_ptr''b'是'a'保证为空?
指定移动后是否为任何标准类的状态?
我有一个结构:
struct Params {
std::shared_ptr<void> user_data;
/* ... */
};
Run Code Online (Sandbox Code Playgroud)
我想这样使用它:
int main() {
std::shared_ptr<SpecializedParams> sp(new SpecializedParams(100));
Params params;
/* ... */
params.user_data = std::static_pointer_cast<void>(sp);
/* ... */
std::shared_ptr<SpecializedParams> sp2 =
std::static_pointer_cast<SpecializedParams>(
params.user_data
);
/* ... */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这有效且安全吗?
我有一个在C++中的shared_ptr中保存的对象.该对象是通过python中的python绑定访问的,并传递给另一个试图保持它的绑定C++函数.看来,当对象从C++转到Python时,它会从shared_ptr转换为python对象.然后,当它返回到C++时,它将从python对象转换为新的shared_ptr,但是这个shared_ptr与初始持有shared_ptr无关.
是否可以设置boost-python绑定,以便从python对象到shared_ptr的转换引用原始的shared_ptr内部?
下面是我用来显示问题的删节代码.
在此示例中,对象最初保存在名为s_inital的shared_ptr中.它是通过getSharedPtr函数从python中获取的,然后通过putSharedPtr函数推回到C++中.在putSharedPtr里面,它被复制到weak_ptr s_copied中.检查调试器中的指针显示putSharedPtr中使用的shared_ptr与s_initial没有相同的引用计数内部.最后的断言将触发,因为弱指针s_copied仅与单个强指针(putSharedPtr中使用的指针)相关,并且一旦putSharedPtr完成,该指针就被破坏了.
static shared_ptr<Captured> s_initial;
static weak_ptr<Captured> s_copied;
class UseSharedPtr
{
public:
shared_ptr<Captured> getSharedPtr()
{
return s_initial;
}
void putSharedPtr(shared_ptr<Captured> ptr)
{
s_copied = ptr;
}
};
BOOST_PYTHON_MODULE(test)
{
class_<Captured, shared_ptr<Captured>, boost::noncopyable>("Captured", no_init);
class_<UseSharedPtr, boost::noncopyable>("UseSharedPtr", init<>())
.def("getSharedPtr", &UseSharedPtr::getSharedPtr)
.def("putSharedPtr", &UseSharedPtr::putSharedPtr)
;
}
s_initial = make_shared<Captured>();
const char* chunk = "\
from test import UseSharedPtr \n\
x = UseSharedPtr() \n\
ptr = x.getSharedPtr() \n\
x.putSharedPtr(ptr)\n\
del x \n\
del ptr \n\
";
object result = exec(chunk, mainNamespace, mainNamespace); …Run Code Online (Sandbox Code Playgroud) [跟进这个问题]
最近,我一直在处理一些关于c风格数组的智能指针.我最终做了推荐的事情,并使用智能指针代替向量,但在那段时间,我得到了一些建议:不要使用shared_ptr<T>对象来管理最初制作的数组,make_unique<T[]>因为它不会调用delete[]而是delete.
这对我来说似乎不合逻辑,我检查了Coliru和标准:
这段代码:
#include <iostream>
#include <memory>
int main()
{
std::cout << "start!\n";
auto customArrayAllocator = [](unsigned int num){
std::cout << "custom array allocator\n";
return new int[num];
};
std::cout << "allocator constructed\n";
auto customArrayDeleter = [](int *ptr){
std::cout << "custom array deleter\n";
delete[] ptr;
};
std::cout << "deleter constructed\n";
std::unique_ptr<int[], decltype(customArrayDeleter)>
myUnique(customArrayAllocator(4), customArrayDeleter);
std::cout << "unique_ptr constructed\n";
std::shared_ptr<int>
myShared = std::move(myUnique);
std::cout << "shared_ptr constructed\n";
}
Run Code Online (Sandbox Code Playgroud)
产生这个输出: …
dlopen()是一个C函数,用于在运行时动态加载共享库.因此,如果您不熟悉,该模式是:
dlopen("libpath", flag)到void *handle图书馆dlsym(handle, "object_name")得到void *object你想要的东西objectdlclose (handle)卸载库.在C++中,这是所谓的别名构造函数的完美用例std::shared_ptr.模式变为:
std::shared_ptr<void> handlefrom dlopen("libpath", flag)将在调用dlclose()析构函数时调用std::shared_ptr<void> objectfrom handle和dlsym(handle, "object_name")object任何我们想要的地方,完全忘记handle; 当object调用析构函数时,无论何时发生,dlclose()都会自动调用绚丽的图案,效果很好.但是有一个小问题.上面的图案需要从铸void*到whatever_type_object_is*.如果"object_name"引用一个函数(考虑到用例,它大部分时间都是这样),这是未定义的行为.
在C中,有一个黑客来解决这个问题.从dlopen手册页:
// ...
void *handle;
double (*cosine)(double);
// ...
handle = dlopen("libm.so", RTLD_LAZY);
// ...
/* Writing: …Run Code Online (Sandbox Code Playgroud) 我已经看到了几个shared_ptr的实现,例如这里.所有人都宣称ref_count为int*.我不明白,如果只是一个,我们会失去什么int.谢谢!
template <class T>
class shared_ptr {
T* ptr;
int* ref_count;
/**
* Initializes the ref count used for tracking the usage.
*/
void initialize_ref_count() {
if (ref_count != nullptr)
return;
try {
ref_count = new int;
*ref_count = 1;
}
catch (std::bad_alloc& e) {
std::cerr << "Memory allocation error: " << e.what();
}
}
}
Run Code Online (Sandbox Code Playgroud) 我试着寻找答案,但找不到任何有助于理解幕后发生的事情.
假设我们有以下内容:
class Base
{
public:
virtual int request() = 0;
void* operator new(long unsigned int size) = delete;
};
class Derived final : public Base
{
public:
int request() override;
};
int Derived::request()
{
return 2;
}
Run Code Online (Sandbox Code Playgroud)
在基类上,我删除了new运算符,因为我不想创建指针.我知道它可能没有任何意义,它只是一个实验.
当我调用g ++时,给我一个编译错误,告诉我删除了新的运算符.正是我所期待的.
int main()
{
auto d = std::make_unique<Derived>();
int value = d->request();
std::cout << "Request value is " << value << "." << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我创建一个shared_ptr,代码编译并运行正常.
auto d = std::make_shared<Derived>();
Run Code Online (Sandbox Code Playgroud)
为什么在创建共享指针时此代码有效.在这种情况下,运营商没有被使用?
shared-ptr ×10
c++ ×9
boost ×3
c++11 ×3
memory-leaks ×2
boost-python ×1
c++14 ×1
casting ×1
make-shared ×1
memory ×1
new-operator ×1
qt ×1
unique-ptr ×1