我一直在读 Rust 书,在第 15.3 章中他们介绍了 Drop 特征。它说该特征对于实现智能指针很重要(“对智能指针模式重要的第二个特征是 Drop”),但从提供的示例中我看不出原因:
\nstruct CustomSmartPointer {\n data: String,\n}\n\nimpl Drop for CustomSmartPointer {\n fn drop(&mut self) {\n println!("Dropping CustomSmartPointer with data `{}`!", self.data);\n }\n}\n\nfn main() {\n let c = CustomSmartPointer {\n data: String::from("my stuff"),\n };\n let d = CustomSmartPointer {\n data: String::from("other stuff"),\n };\n println!("CustomSmartPointers created.");\n}\nRun Code Online (Sandbox Code Playgroud)\n他们只是在容器超出范围之前打印容器拥有的值(根据我的理解,无论如何它都会被删除)。
\n关于这一点,他们说:“我们\xe2\x80\x99在这里打印一些文本,以直观地演示 Rust 何时调用 drop。”
\n是的,但是没有提供任何示例来说明该特征实际上如何有用(我猜,除了可能释放的日志资源之外)。
\n所以我的问题是:在这种情况下 Drop 实现有何重要性?忽略它是否会导致内存泄漏或其他问题?我觉得我完全没有抓住要点。有人可以提供一个用例,除了在值超出范围之前打印值之外,还可以执行其他操作吗?
\n我尝试删除 drop 实现,但这并没有改变任何内容,除了当 CustomSmartPointer 超出范围时没有打印任何内容。没有编译器错误。
\n假设我有一个从某些 API 生成的数据向量。它仅用于绘图。
vector<double> LineData = generateData();
Run Code Online (Sandbox Code Playgroud)
我还有一个类可以进行绘图和管理数据
class LineChart
{
public:
LineChart(vector* data):m_data{data}{}
vector<double> *m_data;
void plot();
};
LineChart lc {&LineData}
Run Code Online (Sandbox Code Playgroud)
由于向量仅用于绘图,因此我希望该类拥有完全所有权。所以我想将原始指针更改为 unique_ptr。
通常,unique_ptr 是从 new 或 make_unique 创建的,而不是现有对象。我可以复制该向量,然后将其移至班级。
unique_ptr<vector> data = make_unique<vector>(LineData)
Run Code Online (Sandbox Code Playgroud)
但是复制向量会产生不必要的开销,因为我已经有了数据。此外,原始向量在堆栈上变得重复并且不执行任何操作。
那么在这种情况下,是否有一些有效的方法将现有对象的所有权传递给类?最好的做法是什么?
我正在阅读一本书中有关智能指针的内容,其中指定不允许抛出自定义删除器。但我无法弄清楚其中的原因。为什么不允许他们投掷?
我搜索了一下但找不到任何正确回答我的问题的东西(我已经读过这个,这个和这个)
我目前正在尝试使用具有多态性的智能指针.
当我尝试使用指向实现的指针创建指向抽象类的智能指针时,即:
std::shared_ptr<Abstract> ptr = std::make_shared(new Implementation);
Run Code Online (Sandbox Code Playgroud)
我的编译器(MSVC2012)显示有关创建Abstract不可能的实例的错误,因为它具有纯虚拟,即使我尝试创建指针Implementation.
在这种情况下,我可能只是使用完全错误的智能指针,但后来我不知道我做错了什么(并且Visual Studio没有强调我提到的行).
我想知道当需要多态时是否可以使用智能指针,如果是,那么必须如何完成.
注意:我知道协方差,以及shared_ptr 不是继承shared_ptr的类型,但认为智能指针会处理这个问题.
编辑:
根据要求,真正的代码行是:
std::shared_ptr<ISpectrometer> ret = std::make_shared<OOSpectrometer>(m_spectroWrapper);
Run Code Online (Sandbox Code Playgroud)
随着OOSpectrometer从抽象类继承ISpectrometer(和m_spectroWrapper简单的参数).
错误MSVC给我(它是法语,所以可能与英语消息不同)是
error C2259: OOSpectrometer : can't instantiate an abstract class due to the following members :
Run Code Online (Sandbox Code Playgroud)
然后它列出了所在的纯虚函数ISpectrometer.
我想从参考更新智能指针。
shared_ptr<My_Toy> my_toy_ptr;
// Something...
void update(shared_ptr<My_Toy> my_toy_ptr, My_Toy& toy){
my_toy_ptr = &toy;
}
Run Code Online (Sandbox Code Playgroud)
...但是他的代码产生了错误。
我该怎么做?
根据这篇文章,使用smart_ptr包装数组的好方法是定义一个删除函数,并将删除函数单独传递给带有原始数组的smart_ptr.
我将重构我的代码,比如使用smart_ptr包装原始数组.这是一个例子:
原始代码:
class MyList{
public:
MyList(int size = 0);
void Resize(int size);
~MyList();
private:
int* myArray;
int* head_;
size_t size_;
}
MyList::MyList(int size){
myArray = new int[size]; //allocated memory when object is being created
head_ = list_;
size_ = size;
}
void MyList::Resize(int size) {
if (!list_) {
delete myArray;
size_ = 0;
}
myArray = new int[size];
head_ = list_;
size_ = size;
}
MyList::~MyList(){
delete myArray;
head …Run Code Online (Sandbox Code Playgroud) c++ pointers memory-management smart-pointers dynamic-memory-allocation
我有一个课程,它拥有它的孩子的所有权:
class Child
{
public:
Child() {}
~Child() {}
};
class Parent : public QObject
{
Q_OBJECT
public:
explicit Parent(QObject *parent = 0): QObject(parent) {}
~Parent()
{
qDeleteAll(m_children);
}
void addChild(Child *ch)
{
m_children.append(ch);
}
private:
QList<Child *> m_children;
};
Run Code Online (Sandbox Code Playgroud)
Child删除后,Parent使用addChild方法添加到类中的实例将Parent被删除.
以下使用将导致双子女破坏:
int main()
{
{
Parent father;
Child child;
father.addChild( &child );
}
//child is out of scope now and gets destroyed
//father gets destroyed too
//father's destructor deletes child AGAIN!
//crash! …Run Code Online (Sandbox Code Playgroud) 对于通用标题很抱歉,但我只能描述正在发生的事情.
std::unique_ptr<int> qq() {
int b = 11;
std::unique_ptr<int> f(&b);
return f;
}
int main() {
std::unique_ptr<int> q = qq();
int *p = q.release();
*p = 11;
std::cout << *p << "\n";
std::cout << *p << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出
11
32767 // why not 11?
Run Code Online (Sandbox Code Playgroud)
返回return std::move(f)结果输出
11
0 // why not 11?
Run Code Online (Sandbox Code Playgroud) 我对所有C++编码器都有一个小问题!对于您来说,它是否与"C++哲学"兼容,以重新编码您自己的智能指针.实际上我将shared_ptr与weak_ptr一起用于项目,但它使代码过于复杂.我当然可以使用raw_ptr,但是......它是"普通c"......所以你怎么看待它?我应该重新编写自己的智能指针还是继续将shared_ptr与weak_ptr一起使用
当我使用std :: make_shared时,Valgrind给了我一些内存泄漏:
TEST_F(CTestChild, add_gran_child) {
auto child{ std::make_shared<CChild>(TType::Home, std::make_shared<CMockParent>()) };
NiceMock<CMockCaller> caller;
auto gran_child( std::make_shared<CMockGranChild>(TType::Girl, child, caller) );
child->Add(gran_child);
EXPECT_EQ(child->GetCount(), 1);
}
class CMockParent : CParent{
public:
void something(void) override {}
}
class CParent{
public:
virtual void something(void) = 0;
}
class CChild{
public:
CChild(TType, shared_ptr<CParent> a) : _parent(a) {}
void Add(shared_ptr<CGranChild> a) { _list.push_back(a) }
shared_ptr<CParent> _parent;
TList<shared_ptr<CGranChild>> _list;
}
class CGranChild{
public:
CGranChild(TType, shared_ptr<CChild> a) : i_parent(a) {}
shared_ptr<CChild> _parent;
}
Run Code Online (Sandbox Code Playgroud)
为什么make_shared会给我一个内存泄漏?
编辑:我已经包含了类的摘要,以便更好地理解代码.
smart-pointers ×10
c++ ×9
pointers ×4
c++11 ×3
shared-ptr ×3
unique-ptr ×2
class ×1
object ×1
polymorphism ×1
qt ×1
reference ×1
rust ×1
std ×1
weak-ptr ×1