相关疑难解决方法(0)

管理外部资源(类似于C++中的RAII?)

在常见的lisp中,管理外部资源(套接字,文件系统句柄等)的首选方法是什么?

我试图在常见的lisp中制作一个简单的opengl 2d平台游戏.问题是我不太确定如何跟踪OpenGL纹理(必须在glDeleteTextures不再需要时删除它们).

在C++中,我更喜欢使用以下方案:

  1. 制作纹理类
  2. 为该纹理类制作智能/弱指针
  3. 将纹理存储在地图(字典/散列表)中,将文件名映射到纹理的弱指针.
  4. 当请求新纹理时,查看map,看看是否有一个非null(零)弱指针可用.如果可用,则返回现有对象,否则加载新纹理.

但是,我不太确定如何将此方案移植到常见的lisp,因为:

  1. 没有破坏者.
  2. 有垃圾收集器,似乎我的实现(windows平台上的clozureCL)支持终结器,但据我所知,不建议在常见的lisp中使用终结器,因为它们不是确定性的.
  3. 管理资源的首选方法在(with-*那里看起来不合适,因为资源可以在函数调用的中间共享和加载/卸载.

据我所知,有几种方法可用:

  1. 放弃自动资源管理,并手动完成.
  2. 使用宏实现类似于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)

opengl common-lisp

10
推荐指数
1
解决办法
452
查看次数

对象按值传递时调用的析构函数

即使通过普通的按值调用参数传递机制将对象传递给函数,理论上它们可以保护和隔离调用参数,但是仍然可能发生可能影响甚至损坏的副作用,用作参数的对象.例如,如果用作参数的对象分配内存并在销毁时释放该内存,那么在调用析构函数时,函数内部的本地副本将释放相同的内存.这将使原始物体损坏并且实际上无用.

这是用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)

c++

10
推荐指数
1
解决办法
4314
查看次数

scoped_ptr所有权

可能重复:
什么是智能指针,什么时候应该使用?

我正在阅读一篇文章,我找到了一个小例子来证明使用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,表示不打算或不允许所有权转移.

也许作为这个主题的初学者开始是错误的文章,但上述内容究竟意味着什么呢?

c++ smart-pointers

9
推荐指数
1
解决办法
2973
查看次数

为什么我要在这种情况下使用智能指针?

我从来没有使用任何类型的智能指针,但当主题是指针时,我几乎无处不在地阅读它们.我知道有些情况下智能指针比原始指针更好用,因为在某种程度上它们可以管理指针的所有权.但是,我仍然不知道,"我不需要智能指针"和"这是智能指针的情况"之间的界限.

可以说,我有以下情况:

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++ pointers smart-pointers

8
推荐指数
1
解决办法
218
查看次数

C C++中内存泄漏的原因

C C++中内存泄漏的原因是什么(除了通常分配内存而忘记解除分配内存)

c c++ memory-management

7
推荐指数
4
解决办法
6711
查看次数

安全数组删除

我是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

编辑:我知道还有很多其他的可能性,更多的"现代"方法和更舒适的解决方案.但在这种情况下,我们明确告诉使用指针和数组(仅限教育目的).

c++ arrays

7
推荐指数
3
解决办法
924
查看次数

C++默认构造函数,用新对象初始化指针

我有以下问题:在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++ pointers class dynamic default-constructor

6
推荐指数
1
解决办法
3万
查看次数

在现代C++中使用非智能指针

简短版本:
在现代C++中使用非智能指针是否有任何可接受的理由?

长版:
我们有一个包含大量旧C++代码的庞大产品,现在我们正在尝试将其重构为现代C++时代.除了所有旧式代码之外,还有大量的指针传递(主要是使用SAL注释来提供一些安全感),我想知道是否应该将它们全部更改为智能指针,或者可能将其中的一些保留为智能指针. ?
试图转换其中的一些代码,我最终得到了一个代码,它可以简单地论证使用智能指针.

所以问题是:是否存在使用智能指针这样的事情?
换句话说:这些天非智能指针是否有可接受的场景?

c++ refactoring pointers c++11

6
推荐指数
2
解决办法
976
查看次数

具有可选所有权的智能指针

我试图允许一个类包含一个指针,该指针可以是自有指针或借用指针。在前一种情况下,它应该销毁所拥有的对象本身;在后一种情况下,它不应该破坏所指向的对象。

在代码中,我有类 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被破坏时,它会破坏c1b1b2。理想情况下, 的销毁b2应该删除匿名C实例,但是 的销毁b1不应删除任何内容(因为c1将被 A 直接销毁)。

我可以使用什么样的智能指针来实现此目的?或者,最好的解决方案只是将所有权标志传递给 B 吗?

c++ smart-pointers

6
推荐指数
1
解决办法
1657
查看次数

是否可以创建一个可用于创建任何类的"新"实例的泛型方法或类?

通常情况下,如果我有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

这可能吗 ?一个简单的办法是同时具有FooBar一些类型继承,也就是说Baz,并已重载方法返回一个Baz,你转换回FooBar...

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)

但这里的问题是你必须写:

  1. 支持每个类的方法
  2. 并为每种构造函数签名.

目标是编写单个类,方法或宏,我们可以调用一个函数(并传递任何参数),但调用传入的对象的正确构造函数.这可能吗 ?

这个问题的目的是简单地探究是否可以在C++中做这样的事情.请不要提出共享指针,独特的指针,使用新的陷阱,因为这是偏离主题.

编辑:我想只使用STL,并避免使用像Boost ....

c++ templates variadic-templates perfect-forwarding c++11

6
推荐指数
2
解决办法
721
查看次数