给一个需要原始指针的函数什么?
What to give a function that expects a raw pointer?
我正在使用一个库,为了构造我使用的某些对象,它需要一个指向对象的原始指针。我不确定它会用指针做什么,为了让我的代码尽可能安全,我应该传递给这个函数什么?
- 使用唯一指针 - 如果他们决定删除指针,我将进行双删除
- 跟踪原始指针 - 不好,因为我必须记住写删除,但它仍然可以是双删除
- 使用自动持续时间并给他们一个指针
给他们一个参考[=32=] - 如果他们调用 delete 他们的代码会出错
- 使用共享指针 - 与唯一指针相同的双删除问题,但现在我的作用域不会伤害它们的指针
根据我的阅读,选项 3 似乎是我应该做的 - 他们不应该在指针上调用 delete,并且这种格式强制执行了这一点。但是,如果我不知道他们现在或将来是否会根据我给他们的参考调用 delete 怎么办?使用共享指针并说“双重删除不是我的错”?
#include <memory>
#include <iostream>
class ComplexObj {
public:
ComplexObj() : m_field(0) {}
ComplexObj(int data) : m_field(data) {}
void print() { std::cout << m_field << std::endl; }
private:
int m_field;
};
class BlackBox {
public:
BlackBox(ComplexObj* data) {
m_field = *data;
// Do other things I guess...
delete data;
std::cout << "Construction complete" << std::endl;
}
void print_data() { m_field.print(); }
private:
ComplexObj m_field;
};
int main(int argc, char* argv[]) {
// Use a smart pointer
std::unique_ptr<ComplexObj> my_ptr(new ComplexObj(1));
BlackBox obj1 = BlackBox(my_ptr.get());
obj1.print_data();
my_ptr->print(); // Bad data, since BlackBox free'd
// double delete when my_ptr goes out of scope
// Manually manage the memory
ComplexObj* manual = new ComplexObj(2);
BlackBox obj2 = BlackBox(manual);
obj2.print_data();
manual->print(); // Bad data, since BlackBox free'd
delete manual; // Pair new and delete, but this is a double delete
// Edit: use auto-duration and give them a pointer
ComplexObj by_ref(3);
BlackBox obj3 = BlackBox(&by_ref); // they can't call delete on the pointer they have
obj3.print_data();
by_ref.print();
// Use a shared pointer
std::shared_ptr<ComplexObj> our_ptr(new ComplexObj(4));
BlackBox obj4 = BlackBox(our_ptr.get());
obj4.print_data();
our_ptr->print(); // Bad data, they have free'd
// double delete when our_ptr goes out of scope
return 0;
}
我读到的与此主题相关的其他问题...
- I think I am case 2 and should pass by reference
你无法用你所掌握的信息解决这个问题。所有的选择都会产生垃圾。
您必须阅读所用 API 的文档。
在不知道他们是否拥有指针所有权的情况下执行您的 4 个答案中的任何一个都会导致问题。
生活有时很糟糕。
如果你有一个腐败或敌对的 API,唯一安全的做法是在一个单独的进程中与它交互,小心地清除所有通信,然后关闭进程。
如果 API 没有损坏或敌对,您应该能够知道它是否正在取得所指向对象的所有权。在不知道这是新手 C++ 程序员的情况下调用 API 是一个常见的错误。不要这样做。是的,这很糟糕。
如果这个 API 完全是内部的并且您有任何控制权,请设法使所有“拥有指针”参数成为 std::unique_ptr<>
。这在 API 中明确表示您打算拥有该对象并稍后将其删除。
我正在使用一个库,为了构造我使用的某些对象,它需要一个指向对象的原始指针。我不确定它会用指针做什么,为了让我的代码尽可能安全,我应该传递给这个函数什么?
- 使用唯一指针 - 如果他们决定删除指针,我将进行双删除
- 跟踪原始指针 - 不好,因为我必须记住写删除,但它仍然可以是双删除
- 使用自动持续时间并给他们一个指针
给他们一个参考[=32=] - 如果他们调用 delete 他们的代码会出错
- 使用共享指针 - 与唯一指针相同的双删除问题,但现在我的作用域不会伤害它们的指针
根据我的阅读,选项 3 似乎是我应该做的 - 他们不应该在指针上调用 delete,并且这种格式强制执行了这一点。但是,如果我不知道他们现在或将来是否会根据我给他们的参考调用 delete 怎么办?使用共享指针并说“双重删除不是我的错”?
#include <memory>
#include <iostream>
class ComplexObj {
public:
ComplexObj() : m_field(0) {}
ComplexObj(int data) : m_field(data) {}
void print() { std::cout << m_field << std::endl; }
private:
int m_field;
};
class BlackBox {
public:
BlackBox(ComplexObj* data) {
m_field = *data;
// Do other things I guess...
delete data;
std::cout << "Construction complete" << std::endl;
}
void print_data() { m_field.print(); }
private:
ComplexObj m_field;
};
int main(int argc, char* argv[]) {
// Use a smart pointer
std::unique_ptr<ComplexObj> my_ptr(new ComplexObj(1));
BlackBox obj1 = BlackBox(my_ptr.get());
obj1.print_data();
my_ptr->print(); // Bad data, since BlackBox free'd
// double delete when my_ptr goes out of scope
// Manually manage the memory
ComplexObj* manual = new ComplexObj(2);
BlackBox obj2 = BlackBox(manual);
obj2.print_data();
manual->print(); // Bad data, since BlackBox free'd
delete manual; // Pair new and delete, but this is a double delete
// Edit: use auto-duration and give them a pointer
ComplexObj by_ref(3);
BlackBox obj3 = BlackBox(&by_ref); // they can't call delete on the pointer they have
obj3.print_data();
by_ref.print();
// Use a shared pointer
std::shared_ptr<ComplexObj> our_ptr(new ComplexObj(4));
BlackBox obj4 = BlackBox(our_ptr.get());
obj4.print_data();
our_ptr->print(); // Bad data, they have free'd
// double delete when our_ptr goes out of scope
return 0;
}
我读到的与此主题相关的其他问题...
- I think I am case 2 and should pass by reference
你无法用你所掌握的信息解决这个问题。所有的选择都会产生垃圾。
您必须阅读所用 API 的文档。
在不知道他们是否拥有指针所有权的情况下执行您的 4 个答案中的任何一个都会导致问题。
生活有时很糟糕。
如果你有一个腐败或敌对的 API,唯一安全的做法是在一个单独的进程中与它交互,小心地清除所有通信,然后关闭进程。
如果 API 没有损坏或敌对,您应该能够知道它是否正在取得所指向对象的所有权。在不知道这是新手 C++ 程序员的情况下调用 API 是一个常见的错误。不要这样做。是的,这很糟糕。
如果这个 API 完全是内部的并且您有任何控制权,请设法使所有“拥有指针”参数成为 std::unique_ptr<>
。这在 API 中明确表示您打算拥有该对象并稍后将其删除。