在常见的lisp中,管理外部资源(套接字,文件系统句柄等)的首选方法是什么?
我试图在常见的lisp中制作一个简单的opengl 2d平台游戏.问题是我不太确定如何跟踪OpenGL纹理(必须在glDeleteTextures不再需要时删除它们).
在C++中,我更喜欢使用以下方案:
但是,我不太确定如何将此方案移植到常见的lisp,因为:
(with-*那里看起来不合适,因为资源可以在函数调用的中间共享和加载/卸载.据我所知,有几种方法可用:
使用宏实现类似于C++ RAII,weakpointer和smartpointer的东西(这段代码可能不起作用):
(defclass destructible () ())
(defmethod destroy ((obj destructible)) (print (format nil "destroy: ~A" obj)))
(defparameter *destructible-classes-list* nil)
(defmethod initialize-instance :after ((obj destructible) &key)
(progn
(push *destructible-classes-list* obj)
(print (format nil "init-instance: ~A" obj))))
(defmacro with-cleanup (&rest body)
`(let ((*destructible-classes-list* nil))
(progn ,@body (mapcar (lambda (x) (destroy x)) *destructible-classes-list*))))
(defclass refdata (destructible)
((value :accessor refdata-value :initform nil)
(ref :accessor refdata-ref :initform …Run Code Online (Sandbox Code Playgroud)即使通过普通的按值调用参数传递机制将对象传递给函数,理论上它们可以保护和隔离调用参数,但是仍然可能发生可能影响甚至损坏的副作用,用作参数的对象.例如,如果用作参数的对象分配内存并在销毁时释放该内存,那么在调用析构函数时,函数内部的本地副本将释放相同的内存.这将使原始物体损坏并且实际上无用.
这是用C++编写的:完整参考
在这个程序在这里
#include<iostream>
using namespace std;
class Sample
{
public:
int *ptr;
Sample(int i)
{
ptr = new int(i);
}
~Sample()
{
cout<<"destroyed";
delete ptr;
}
void PrintVal()
{
cout << "The value is " << *ptr;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
}
Run Code Online (Sandbox Code Playgroud)
它会在对象s1从对象返回时被销毁时生成运行时错误.我无法弄清楚为什么会发生这种情况,因为应该制作副本.我想也许是因为班级定义中没有复制构造函数.但我很惊讶地发现,如果使用这个函数声明
void SomeFunc(Sample &x)
{
cout << "Say i am in someFunc " << endl;
} …Run Code Online (Sandbox Code Playgroud) 可能重复:
什么是智能指针,什么时候应该使用?
我正在阅读一篇文章,我找到了一个小例子来证明使用boost::scoped_ptr<T>:
#include <cstdlib>
#include <iostream>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
static int count = 0;
class printer
{
int m_id;
public:
printer(void) :
m_id(count++)
{
}
~printer(void)
{
std::cout << "Printer " << m_id
<< " destroyed" << std::endl;
}
};
int
main(void)
{
boost::scoped_ptr<printer> p1(new printer);
boost::scoped_ptr<printer> p2(new printer);
std::cout << "Exiting test program" << std::endl;
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我在文章中唯一不理解的是这句话:
使用时
scoped_ptr,表示不打算或不允许所有权转移.
也许作为这个主题的初学者开始是错误的文章,但上述内容究竟意味着什么呢?
我从来没有使用任何类型的智能指针,但当主题是指针时,我几乎无处不在地阅读它们.我知道有些情况下智能指针比原始指针更好用,因为在某种程度上它们可以管理指针的所有权.但是,我仍然不知道,"我不需要智能指针"和"这是智能指针的情况"之间的界限.
可以说,我有以下情况:
class A {
public:
double get1(){return 1;}
double get2(){return 2;}
};
class SomeUtilityClass {
public:
SomeUtilityClass(A* a) : a(a) {}
double getResult(){return a->get1() + a->get2();}
void setA(A* a){a = a;}
private:
A* a;
};
int main(int argc, char** argv) {
A a;
SomeUtilityClass u(&a);
std::cout << u.getResult() << std::endl;
A a2;
u.setA(&a2);
std::cout << u.getResult() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这当然是一个过于简单的例子.我的意思是SomeUtilityClass不应该"拥有"一个实例A(因为它只是一个实用类),因此它只是一个指针.
关于指针,我所知道的唯一可能出错的是:
SomeUtilityClass 可以使用空指针进行实例化SomeUtilityClass注意到它智能指针如何帮助避免这个问题?在这种情况下,使用智能指针可以获得哪些其他好处?
PS:我知道智能指针有几个问题(例如这个).但是,如果您能告诉我有关此特定示例的影响,我将不胜感激.
我是C++的新手,我并不完全确定如何以安全的方式处理数组和指针.在我的班上,我有一个叫做项目的成员:
Item * items;
Run Code Online (Sandbox Code Playgroud)
在我的类方法read()中我打开一个文件并从这个文件中读取项目.我相应地分配空间:
items = new Item[item_count];
Run Code Online (Sandbox Code Playgroud)
item_count作为文件中的变量给出,并在创建任何项目之前预先读取.在我班级的解构器中,我再次释放这样的内存:
delete[] items;
Run Code Online (Sandbox Code Playgroud)
但是如果我read()在执行解构函数之前调用该方法两次,则第一个数组的内存将无法正确释放.我想在分配新内存之前事先在read方法中释放它.但是如何检查是否已为阵列分配了一些内存items?
编辑:我知道还有很多其他的可能性,更多的"现代"方法和更舒适的解决方案.但在这种情况下,我们明确告诉使用指针和数组(仅限教育目的).
我有以下问题:在myClass中我想默认初始化一个指向yourClass的指针,带有一个新的yourClass地址.不幸的是,如果我想在任何一点删除指针,我得到一个(核心转储).
class myClass
{
protected:
yourClass * yc;
public:
myClass() { yc = new yourClass(); }
myClass(yourClass * tyc ) { delete yc; yc = tyc; }
~myClass() { delete yc; yc = NULL; }
void setMyClass (yourClass * tyc) { delete yc; yc = tyc; }
void print () { yc->print(); }
};
int main()
{
yourClass b (//parameter);
myClass * a = new myClass();
a->print();
a->setMyClass(&b)
a->print();
delete a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
a的print()应该产生两种不同的打印,取决于//参数.
我认为你的等级是yc; 而不是yourClass*yc,但我想知道它是否可行.
编辑: 我以下面的方式重新编写代码,它的工作原理.仍然看起来很复杂,聪明的指针看起来很有希望,我仍然没有应用"三个规则".这里的代码.谢谢大家.
class …Run Code Online (Sandbox Code Playgroud) 简短版本:
在现代C++中使用非智能指针是否有任何可接受的理由?
长版:
我们有一个包含大量旧C++代码的庞大产品,现在我们正在尝试将其重构为现代C++时代.除了所有旧式代码之外,还有大量的指针传递(主要是使用SAL注释来提供一些安全感),我想知道是否应该将它们全部更改为智能指针,或者可能将其中的一些保留为智能指针. ?
试图转换其中的一些代码,我最终得到了一个代码,它可以简单地论证使用智能指针.
所以问题是:是否存在使用智能指针这样的事情?
换句话说:这些天非智能指针是否有可接受的场景?
我试图允许一个类包含一个指针,该指针可以是自有指针或借用指针。在前一种情况下,它应该销毁所拥有的对象本身;在后一种情况下,它不应该破坏所指向的对象。
在代码中,我有类 A、B 和 C。我的目标是以下(简化的)定义,其中 B 是需要拥有指针的类:
class C {
...
};
class B {
C *c;
B(C *c) : c(c) {
}
};
class A {
C c1;
B b1, b2;
// b2 leaks pointer to C
A() : b1(&c1), b2(new C()) {
}
};
Run Code Online (Sandbox Code Playgroud)
当 的实例A被破坏时,它会破坏c1、b1和b2。理想情况下, 的销毁b2应该删除匿名C实例,但是 的销毁b1不应删除任何内容(因为c1将被 A 直接销毁)。
我可以使用什么样的智能指针来实现此目的?或者,最好的解决方案只是将所有权标志传递给 B 吗?
通常情况下,如果我有a Foo或a Bar,我会做类似的事情:
Foo* foo = new Foo();
Bar* bar = new Bar(2,3,5);
Run Code Online (Sandbox Code Playgroud)
有没有办法使用模板或宏,我可以构建一个函数,这样我可以做类似的事情:
Foo* foo = MyAwesomeFunc(Foo);
Bar* bar = MyAwesomeFunc(Bar,2,3,5);
Run Code Online (Sandbox Code Playgroud)
实际的方法签名
MyAwesomeFunc对我来说并不重要.
Foo并且Bar不需要以任何可能的方式相关,并且可能具有完全不同的构造函数.此外,我可能希望将来支持任意数量的类,而无需实际修改代码MyAwesomeFunc
这可能吗 ?一个简单的办法是同时具有Foo和Bar一些类型继承,也就是说Baz,并已重载方法返回一个Baz,你转换回Foo或Bar...
Baz* MyAwesomeFunc(){
return new Foo();
}
Baz* MyAwesomeFunc(int a,int b,int c){
return new Bar(a,b,c);
}
Run Code Online (Sandbox Code Playgroud)
但这里的问题是你必须写:
目标是编写单个类,方法或宏,我们可以调用一个函数(并传递任何参数),但调用传入的对象的正确构造函数.这可能吗 ?
这个问题的目的是简单地探究是否可以在C++中做这样的事情.请不要提出共享指针,独特的指针,使用新的陷阱,因为这是偏离主题.
编辑:我想只使用STL,并避免使用像Boost ....