以下代码生成悬空引用:
int main()
{
int *myArray = new int[2]{ 100, 200 };
int &ref = myArray[0];
delete[] myArray;
cout << ref; // Use of dangling reference.
}
Run Code Online (Sandbox Code Playgroud)
我知道我不应该删除的磁盘阵列,但在一个大的程序,如果有人有什么删除记忆,而我有一个参考?它可以以某种方式确保没有人删除阵列吗?
什么是反对悬挂引用和悬空指针的最佳策略?
一种是使用C++异常:尝试catch块.但是,当引发异常时,释放动态内存将成为一个问题.
第二种是使用C风格:errno变量
第三个是在错误时返回-1,在成功时返回0 :)
应该选择哪种方式进行中型项目?为什么?还有其他更好的方法..?
我了解面向对象编程的方法,但我已经习惯了Java,直到最近我才接触过C++.
我认为我的问题与语法无关,与C++中的OOP哲学有关.我理解指针和地址与堆栈和堆之间的区别,以及东西,但我仍然觉得我错过了一些东西.
这是一个例子:我有一个包含一些数据的类(Shape).我有另一个类(App)使用了许多形状.
class Square {
private:
int x;
int y;
int size;
public:
/* constructor */
Square(int x, int y, int size);
}
class App {
private:
Square redSquare;
Square blueSquare;
public:
void setup();
void draw();
}
Run Code Online (Sandbox Code Playgroud)
在某些时候,某些东西将实例化我的应用程序并调用setup().问题在于,当我声明App类(在App.hpp中,比方说)时,"redSquare"和"blueSquare"被实例化,而不仅仅是声明.作为一名Java程序员,我将在本例中在setup()中实例化我的类.但是这意味着我不能像上面那样做,我必须将redSquare和blueSquare设置为POINTERS,然后我可以在setup()中使用new创建它们.
但是你会怎么做呢?或者你会使用默认参数创建一个构造函数,如上所述创建redSquare和blueSquare,然后使用像Square.init(x,y,size)之类的东西在App.setup()中设置这些方块的值?或者其他一些方式?
你有没有汇总课程,或只有指针?
我当然可以通过这种方式破解它,所以它可以自己工作,但我有一种感觉,我正在做"Java方式",而不是得到C++程序员的想法.
让我们有一段代码(fstream只是一个例子,我们可以谈论动态内存分配......):
fstream f;
try {
f.open("xxx");
...
f.close();
} catch (...) {
...
}
Run Code Online (Sandbox Code Playgroud)
当出现问题我想关闭()文件(释放内存或其他),但我不知道f的状态.毕竟,异常可能来自f.open().我认为在catch子句中调用f.close()是不安全的,因为我不能再相信f了.
f也可以是一个指向动态分配的数组的指针,我想删除[],但是谁知道抛出异常后它指向的位置...
这可能不是很常见,但是当我绝对无法承受任何额外伤害时,我该怎么办?
我可以考虑立即中止().
谢谢.
我正在从Java转向C++并且非常喜欢它.我不喜欢的一件事是根本不了解内存,因为Java过去常常为我做这件事.
我已经购买了一本书:内存作为C和C++中的编程概念 - Frantisek Franek
我是否有一些很好的网站可以交互式地学习C/C++和内存使用(教程,论坛,用户组)?
无法弄清楚如何准确地说出问题,所以这是一个例子:
鉴于此功能原型:
void Foo(myClass* bar);
Run Code Online (Sandbox Code Playgroud)
我想阻止这种用法:
Foo(new myClass());
Run Code Online (Sandbox Code Playgroud)
而是需要先前创建的对象:
myClass* bar = NULL;
bar = new myClass();
Foo(bar);
Run Code Online (Sandbox Code Playgroud)
要么
myClass bar;
Foo(&bar);
Run Code Online (Sandbox Code Playgroud)
谢谢.
这是一个澄清的例子:
void Mouse::SetImage(BITMAP* image, int focusX, int focusY) {
if(_image) {
set_mouse_sprite(NULL);
set_mouse_sprite_focus(0, 0);
show_mouse(NULL);
destroy_bitmap(_image);
_image = NULL;
}
if(image) {
_image = create_bitmap(image->w, image->h);
clear_bitmap(_image);
blit(image, _image, 0, 0, 0, 0, image->w, image->h);
}
if(image == NULL) {
focusX = 0;
focusY = 0;
}
_focusX = focusX;
_focusY = …Run Code Online (Sandbox Code Playgroud) 以下示例留下可能的内存泄漏,因为析构函数不会针对在其构造函数运行期间处理异常的对象运行.我在哪里处理这个内存泄漏?
#include <exception>
class MyClass {
public:
MyClass()
{
c = new char[5];
throw std::runtime_error("test");
}
~MyClass ()
{
delete[] c;
}
private:
char *c;
};
int main()
{
try
{
MyClass Obj;
}
catch (std::runtime_error)
{
}
}
Run Code Online (Sandbox Code Playgroud) 我目前正在使用opengl进入c ++进行低级编码.我来自一个沉重的objc背景,所以我对内存管理有一些了解,但我似乎无法得到"boost"库如何管理容器类型ptr_vector.
我认为我的问题与我不知道如何ptr_vector管理自身及其对象的破坏这一事实有关.
请看下面的代码:
// Header file
...
ptr_vector<IObject3D> objects;
...
// Implementation file
...
void ApplicationEngine::init()
{
WavefrontObject3D *object = new WavefrontObject3D("Ninja.obj");
objects.push_back(object);
}
...
Run Code Online (Sandbox Code Playgroud)
所以,对于实际问题:我是否通过"对象"变量在这里创建泄漏?
我习惯于使用objc中的显式调用手动保留和释放我的对象:之前我不得不alloc init使用WavefrontObject3D object,将其添加到数组中,然后release将相同的对象添加到相同的对象中以避免泄漏.
但是当我delete object在push_back调用之后添加一个时,会调用WavefrontObject3D的解构object函数.这给了我一个提示,ptr_vector即不保留object变量.我的假设是否正确?
另外但相关的问题:假设我想要销毁包含类ApplicationEngine,我不必在ptr_vector它管理的元素上调用某种解构函数吗?
我有一些处理,我需要关闭它.代码中有一些地方可以关闭句柄.那么,这是一个正确的关闭方式吗?
HANDLE h;
....
if ( h != INVALID_HANDLE_VALUE ) {
::CloseHandle(h);
h = INVALID_HANDLE_VALUE;
}
Run Code Online (Sandbox Code Playgroud)
关于位图句柄有一个相同的问题:
HBITMAP hb;
....
if ( hb != INVALID_HANDLE_VALUE ) {
::DeleteObject(hb);
hb = INVALID_HANDLE_VALUE;
}
Run Code Online (Sandbox Code Playgroud)
编辑:我想,有一些误解.我知道CloseHandle是关闭手柄.我想知道关闭手柄的正确方法.删除指针时会出现类似的情况.
Foo *foo = new Foo();
// for example there is 2 functions that can delete foo
void bar() {
....
delete foo;
}
void duck() {
....
delete foo;
}
Run Code Online (Sandbox Code Playgroud)
因此,以下代码意味着问题:
bar();
duck();
Run Code Online (Sandbox Code Playgroud)
这种情况有一些解决方法.我们需要定义bar和这样的duck函数:
void bar() {
....
if (foo) …Run Code Online (Sandbox Code Playgroud) 我一直在尝试用c ++创建一个垃圾收集器,我已经将它设计为我的所有基类,称为garbageCandidate,它包含一个静态向量,其中包含指向garbageCandidate的指针,每个garbageCollector实例都在向量上推送"this" .
然后静态函数出现并删除静态向量中的所有指针.
在删除函数的最开始(删除第一个指针)我得到一个错误,说明删除被用于无效指针...
这与静态/动态绑定有关吗?我的意思是:删除操作符是否无法按预期行事,因为我在"父"类上调用delete并且它实际上是一个孩子?
一种避免这种情况的方法是创建虚拟析构函数吗?(或虚拟删除功能)?
还是我完全错过了什么?
ps:用于动态创建的测试的所有对象.