好的,世纪的问题:)
在你说或想什么之前,让我告诉你,我已经读过几个关于这个话题的类似问题,但是我没有找到解决问题的明确方法.我的案例是具体的,我认为是系统程序员的典型案例.
我经常遇到这种情况.我讨厌搞砸了,不知道为什么,可能是因为每个人都在大喊大叫它是坏事.但是直到现在我还没有找到更好的解决方案来解决我的特定场景,而我目前的做法可能比使用goto更难.
这是我的情况:我使用C++(Visual C++)进行Windows应用程序开发,而且我常常在我的例程中使用大量的API.假设以下情况:
int MyMemberFunction()
{
// Some code... //
if (!SomeApi())
{
// Cleanup code... //
return -1;
}
// Some code... //
if (!SomeOtherApi())
{
// Cleanup code... //
return -2;
}
// Some more code... //
if (!AnotherApi())
{
// Cleanup code... //
return -3;
}
// More code here... //
return 0; // Success
}
Run Code Online (Sandbox Code Playgroud)
因此,在每个Api之后我必须检查它是否成功,并且如果没有则中止我的功能.为此,我使用了大量的// Cleanup code... //,通常是重复的,然后是return声明.该功能执行10个任务(例如使用10个Apis),如果任务#6失败,我必须清理以前任务创建的资源.请注意,清理应该由函数本身完成,因此不能使用异常处理.另外,在这种情况下,我无法看到有多少谈论RAII可以帮助我.
我想到的唯一方法是使用goto从所有这些失败案例跳转到一个清理标签,放置在函数的末尾.
有没有更好的方法呢?在这种情况下使用goto会被认为是不好的做法吗?该怎么办?这种情况对我来说非常典型(对于像我这样的系统程序员,我相信).
PS:需要清理的资源属于不同类型.可能存在内存分配,需要关闭的各种系统对象句柄等.
更新:
我认为人们仍然没有得到我想要的东西(可能我解释得很糟糕).我认为伪代码应该足够了,但这是一个实际的例子:
我用CreateFile打开两个文件.如果此步骤失败:我必须清除已打开的文件句柄(如果有).我稍后会阅读一个文件的一部分并写入另一个文件.
我使用SetFilePointer将读指针放在第一个文件中.如果此步骤失败:我必须关闭上一步打开的句柄.
我使用GetFileSize来获取目标文件大小.如果api失败,或文件大小异常,我必须进行清理:与上一步相同.
我分配指定大小的缓冲区从第一个文件读取.如果内存分配失败,我必须再次关闭文件句柄.
我必须使用ReadFile从第一个文件中读取.如果失败,我必须:释放缓冲区内存,并关闭文件句柄.
我使用SetFilePointer将写指针放在第二个文件中.如果失败,则必须进行相同的清理. …
我在以下代码中检测到glibc,有人可以向我解释一下
#include<iostream>
using namespace std;
class Sample
{
public:
int *ptr;
Sample(int i)
{
ptr = new int(i);
}
void PrintVal()
{
cout << "The value is " << *ptr<<endl;
}
~Sample()
{
cout<<"CALLED\n";
delete ptr;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
x.PrintVal();
//cout<<*(s1.ptr)<<endl;
}
int main()
{
Sample s1=10;
cout<<*(s1.ptr)<<endl;
SomeFunc(s1);
cout<<"HERE\n";
cout<<*(s1.ptr)<<endl;
}
Run Code Online (Sandbox Code Playgroud)
在这里调用cout<<*(s1.ptr)<<endl;glib被检测到.我无法理解的是,为什么即使没有为s1调用desructor,引用也会被删除.
我真的没有得到模板std :: vector的字段,第一个指定类型,例如一个类,但我没有得到分配器,指针和引用变量.
我将提供一个简单的例子,我想使用类人的向量,所以我不得不对模板向量说:嘿,存储我一些人的,但我还必须告诉向量如何分配该类.(1)该示例的语法如何?
一些代码开头:
旁注,在人的构造函数中,c(2)我应该使用日期*?
class date
{
public:
int m_nMonth;
int m_nDay;
int m_nYear;
int getMonth(return m_nMonth;)
int getDay(return m_nDay;)
int getYear(return m_nYear;)
void setDate(int month, int day, int year)
{
m_nMonth=month;
m_nDay=day;
m_nYear=year;
}
date()
{
setDate(0,0,0);
}
date(int month, int day, int year)
{
setDate(month,day,year);
}
void printDate()
{
printf("%d/%d/%d", m_nMonth, m_nDay, m_nYear);
}
}
class person
{
public:
int m_nID;
char m_sName[128];
char m_sSurname[128];
date m_cBirthDay;
void setName(const char* name)
{ …Run Code Online (Sandbox Code Playgroud) 我正在学习C++.有一个奇怪的案例,我想知道解决方案.假设代码如下
class HumanBeing {
private:
string *name;
int *age;
HumanBeing(string name, int age) {
// what to do in here?
}
};
Run Code Online (Sandbox Code Playgroud)
在Java中我可以使用this.name = name.但是在C++中我能做到this->name = name(它对上面的例子无效),但是当类变量是一个指针时该怎么办?
我来自Java背景,所以这些(指针)的东西对我来说非常混乱.
#include<iostream>
#include<string>
using namespace std;
class Human{
private:
int *age;
string *name;
public:
Human(string iname,int iage)
{
name=new string;
age=new int;
*name=iname;
*age=iage;
}
void display()
{
cout<<"Name "<<*name<<endl<<"Age "<<*age<<endl;
}
~Human(){
delete name;
delete age;
cout<<"Released all memories"<<endl;
}
};
int main()
{
Human *pallavi= new Human("pallavi",21);
pallavi->display();
delete pallavi;
pallavi->display();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我编写了一个简单的程序,它创建了Human类的对象.指定析构函数以删除两个数据变量,即int age和string name.但是在调用析构函数("delete pallavi")并再次显示变量时,我收到的输出是:
姓名
21岁
当然,整个输出是这样的:
名字pallavi
年龄21
释放所有记忆
名字
年龄21.
我的问题是,析构函数不应该释放回忆吗?这是否意味着第二次显示对象(调用析构函数后),Name和age应显示垃圾值?为什么输出显示没有Name的值和21岁的年龄?
我有一个Storage列出的列表Things:
#include <iostream>
#include <list>
#include <functional>
class Thing {
private:
int id;
int value = 0;
static int nextId;
public:
Thing() { this->id = Thing::nextId++; };
int getId() const { return this->id; };
int getValue() const { return this->value; };
void add(int n) { this->value += n; };
};
int Thing::nextId = 1;
class Storage {
private:
std::list<std::reference_wrapper<Thing>> list;
public:
void add(Thing& thing) {
this->list.push_back(thing);
}
Thing& findById(int id) const {
for (std::list<std::reference_wrapper<Thing>>::const_iterator it = …Run Code Online (Sandbox Code Playgroud) 我在想一个奇怪的用例,我想将对象移到nullptr。也许我应该给出一个代码片段:
class Objpair {
public:
Objpair(Obj&& a, Obj&&b) : first(&a), second(&b) { }
private:
Obj* first;
Obj* second;
};
Run Code Online (Sandbox Code Playgroud)
问题在于,当a和b超出范围时,第一和第二指针将悬空。如果我可以将Object a移到第一个指针上,那么应该就不会出现双重释放和作用域问题。如果首先将成员声明为Obj而不是Obj *指针,则直接的first(std :: move(a))将完成此工作。我在这里一定做错了。我正在考虑移动而不是复制,因为我试图将控制权从另一个对象转移到当前对象并提高性能。
使用指针版本是因为我正在考虑成员对象的多态行为。
我正在使用构造函数和析构函数进行测试,我想看看是否可以在不先声明的情况下将对象传递给函数,如下例所示:
#include<iostream>
#include<stdlib.h>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(car* p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
display(new car("HYUNDAI", 2012));
}
Run Code Online (Sandbox Code Playgroud)
该display功能运行良好,并且完全符合我的预期,但我想知道:
new如果我在输入中声明了关键字display,为什么我的用户定义的析构函数没有被调用,并且new导致内存泄漏吗?我是 C++ 新手,尝试了解如何在 C++ 中创建和使用类。为此,我有以下代码:
class MyClass
{
public:
MyClass()
{
_num = 0;
_name = "";
}
MyClass(MyClass* pMyClass)
{
_num = pMyClass->_num;
_name = pMyClass->_name;
}
void PrintValues() { std::cout << _name << ":" << _num << std::endl; }
void SetValues(int number, std::string name)
{
_num = number;
_name = name;
}
private:
int _num;
std::string _name;
};
int main()
{
std::vector<MyClass*> myClassArray;
MyClass myLocalObject = new MyClass();
for (int i = 0; i < 3; i++)
{ …Run Code Online (Sandbox Code Playgroud) Ubuntu 10.10 gcc 4.4.4
我只是在尝试分配和释放.
但是,当一个对象被多次释放时,我试图避免这个问题.
但是,当我测试时,我注意到创建和释放的obj没有返回到null状态.那么有什么条件我可以设置,如果这确实发生将避免?
我也试过在free之后将对象设置为NULL.但是,它仍然试图释放该对象.
这是对这个问题的引用,只是让你知道不重复: 释放已分配的内存
我的代码如下:
#include <stdio.h>
#include "objects.h"
int main(void)
{
obj_t *obj = NULL;
obj = create_object();
destroy_object(obj);
destroy_object(obj);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
==
#ifndef OBJECTS_H_INCLUDED
#define OBJECTS_H_INCLUDED
typedef struct Obj_t obj_t;
obj_t* create_object();
void destroy_object(obj_t *obj);
#endif /* OBJECTS_H_INCLUDED */
Run Code Online (Sandbox Code Playgroud)
==
#include <stdio.h>
#include <stdlib.h>
#include "objects.h"
struct Obj_t {
int obj_id;
};
obj_t* create_object()
{
obj_t *obj = malloc(sizeof obj);
return obj;
}
void destroy_object(obj_t *obj)
{
if(obj != NULL) { …Run Code Online (Sandbox Code Playgroud) c++ ×9
class ×2
constructor ×2
pointers ×2
allocator ×1
c ×1
c++11 ×1
destructor ×1
free ×1
heap-memory ×1
malloc ×1
memory-leaks ×1
move ×1
reference ×1
stack-memory ×1
std ×1
vector ×1