加分 -- 如何在指定的内存区域 new 一个对象?

everandforever 2002-09-14 10:40:36
周一结贴。
原贴:
http://www.csdn.net/expert/topic/998/998086.xml?temp=.7920191
...全文
66 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
xghome 2002-09-15
  • 打赏
  • 举报
回复
又写了一个工程测试了一次
#include "stdafx.h"
#include "iostream.h"

class A
{
public:
A() {cout<<"A()"<<endl;}
~A() {cout<<"~A()"<<endl;}
void* operator new (size_t size,void* pBuffer)
{
cout<<"A::new"<<endl;
return pBuffer;
}
void A1() {cout<<"A1()"<<endl;}
};

int main(void)
{
char pBuffer[1024];
A* a=new (pBuffer) A;
a->A1();
a->~A();
return 0;
}

运行结果
A::new
A()
A1()
~A()

这才正确,呵呵,前面写错了点,不好意思
这个程序编译有一个报警
warning C4291: 'void *__cdecl A::operator new(unsigned int,void *)' : no matching operator delete found; memory will not be freed if initialization throws an exception
C:\VCWork\memObjTest\memObjTest.cpp(12) : see declaration of 'new'
说的是没有与异型new对应的delete,不要去管他就是了,因为这种调用法,最重要的就是不能用delete清除对象,否则,内存指针在对象清除时就被清除了,而推出函数时,自动释放pBuffer时,因为这块内存已经标记清除,肯定出错

很多C++的书籍说,显式调用析构函数是一个高级话题,说的就是这种情况
xghome 2002-09-15
  • 打赏
  • 举报
回复
写错了两点
1、类A中所有函数应该注明public
2、A* a=new (pBuffer) A; //这么写好像比较正确
xghome 2002-09-15
  • 打赏
  • 举报
回复
哪那么麻烦,看着
class A
{
A(){}
~A(){}
void* operator new(void* pBuffer,size_t size) {return pBuffer;}
//重载该对象的new,注意,此处仅为示例,实际时需要计算pBuffer的
//占用情况,不然,一个Buffer就只能创建一个对象了
}

int main(void)
{
char* pBuffer[1024]; //一定要>sizeof(A)
A* a=new A(pBuffer);
....
a->~A(); //这里最重要,通过显式调用析构函数实现对象的delete
}
puppet 2002-09-15
  • 打赏
  • 举报
回复
记得
include <new>
using namespace std;
puppet 2002-09-15
  • 打赏
  • 举报
回复
可以使用Placement new

以下摘自more effective C++ Item 8

There are times when you really want to call a constructor directly. Invoking a constructor on an existing object makes no sense, because constructors initialize objects, and an object can only be initialized — given its first value — once. But occasionally you have some raw memory that's already been allocated, and you need to construct an object in the memory you have. A special version of operator new called placement new allows you to do it.

As an example of how placement new might be used, consider this:

class Widget {
public:
Widget(int widgetSize);
...
};

Widget * constructWidgetInBuffer(void *buffer,
int widgetSize)
{
return new (buffer) Widget(widgetSize);
}

This function returns a pointer to a Widget object that's constructed within the buffer passed to the function. Such a function might be useful for applications using shared memory or memory-mapped I/O, because objects in such applications must be placed at specific addresses or in memory allocated by special routines. (For a different example of how placement new can be used, see Item 4.)

Inside constructWidgetInBuffer, the expression being returned is

new (buffer) Widget(widgetSize)

This looks a little strange at first, but it's just a use of the new operator in which an additional argument (buffer) is being specified for the implicit call that the new operator makes to operator new. The operator new thus called must, in addition to the mandatory size_t argument, accept a void* parameter that points to the memory the object being constructed is to occupy. That operator new is placement new, and it looks like this:

void * operator new(size_t, void *location)
{
return location;
}

This is probably simpler than you expected, but this is all placement new needs to do. After all, the purpose of operator new is to find memory for an object and return a pointer to that memory. In the case of placement new, the caller already knows what the pointer to the memory should be, because the caller knows where the object is supposed to be placed. All placement new has to do, then, is return the pointer that's passed into it. (The unused (but mandatory) size_t parameter has no name to keep compilers from complaining about its not being used; see Item 6.) Placement new is part of the standard C++ library (see Item E49). To use placement new, all you have to do is #include <new> (or, if your compilers don't yet support the new-style header names (again, see Item E49), <new.h>).

If we step back from placement new for a moment, we'll see that the relationship between the new operator and operator new, though you want to create an object on the heap, use the new operator. It both allocates memory and calls a constructor for the object. If you only want to allocate memory, call operator new; no constructor will be called. If you want to customize the memory allocation that takes place when heap objects are created, write your own version of operator new and use the new operator; it will automatically invoke your custom version of operator new. If you want to construct an object in memory you've already got a pointer to, use placement new.

(For additional insights into variants of new and delete, see Item E7 and my article on counting objects.)

AthlonxpX86 2002-09-15
  • 打赏
  • 举报
回复
去学学驱动编程,也许有帮助。
AthlonxpX86 2002-09-15
  • 打赏
  • 举报
回复
用汇编。_asm{........}.
dy_paradise 2002-09-15
  • 打赏
  • 举报
回复
帮你UP了
dreamhorse 2002-09-15
  • 打赏
  • 举报
回复
你的指定区域是什么意思,是系统已经分配了一块区域,你得到它的地址,然后对象在里面生成,还是直接指定地址,让对象在里面生成?
Chiun 2002-09-14
  • 打赏
  • 举报
回复
gz
finix 2002-09-14
  • 打赏
  • 举报
回复
我得方法你试了吗
skqgd 2002-09-14
  • 打赏
  • 举报
回复
有难度...
网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的诊断和测试以及恢复系统功能的工具。小编的确一直都想把这方面的命令做个总结,这次辛苦老范给我们整理了这份实用的秘笈。   Bootcfg   bootcfg 命令启动配置和故障恢复(对于大多数计算机,即 boot.ini 文件)。   含有下列参数的 bootcfg 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 bootcfg 命令。   用法:   bootcfg /default  设置默认引导项。   bootcfg /add    向引导列表中添加 Windows 安装。   bootcfg /rebuild  重复全部 Windows 安装过程并允许用户选择要添加的内容。   注意:使用 bootcfg /rebuild 之前,应先通过 bootcfg /copy 命令备份 boot.ini 文件。   bootcfg /scan    扫描用于 Windows 安装的所有磁盘并显示结果。   注意:这些结果被静态存储,并用于本次会话。如果在本次会话期间磁盘配置发生变化,为获得更新的扫描,必须先重新启动计算机,然后再次扫描磁盘。   bootcfg /list   列出引导列表中已有的条目。   bootcfg /disableredirect 在启动引导程序中禁用重定向。   bootcfg /redirect [ PortBaudRrate] |[ useBiosSettings]   在启动引导程序中通过指定配置启用重定向。   范例: bootcfg /redirect com1 115200 bootcfg /redirect useBiosSettings   hkdsk   创建并显示磁盘的状态报告。Chkdsk 命令还可列出并纠正磁盘上的错误。   含有下列参数的 chkdsk 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 chkdsk 命令。   vol [drive:] [ chkdsk [drive:] [/p] [/r]   参数  无   如果不带任何参数,chkdsk 将显示当前驱动器中的磁盘状态。 drive: 指定要 chkdsk 检查的驱动器。 /p   即使驱动器不在 chkdsk 的检查范围内,也执行彻底检查。该参数不对驱动器做任何更改。 /r   找到坏扇区并恢复可读取的信息。隐含着 /p 参数。   注意 Chkdsk 命令需要 Autochk.exe 文件。如果不能在启动目录(默认为 %systemroot%System32)中找到该文件,将试着在 Windows 安装 CD 中找到它。如果有多引导系统的计算机,必须保证是在包含 Windows 的驱动器上使用该命令。 Diskpart   创建和删除硬盘驱动器上的分区。diskpart 命令仅在使用故障恢复控制台时才可用。   diskpart [ /add |/delete] [device_name |drive_name |partition_name] [size]   参数 无   如果不带任何参数,diskpart 命令将启动 diskpart 的 Windows 字符模式版本。   /add   创建新的分区。   /delete   删除现有分区。   device_name   要创建或删除分区的设备。设备名称可从 map 命令的输出获得。例如,设备名称:   DeviceHardDisk0   drive_name   以驱动器号表示的待删除分区。仅与 /delete 同时使用。以下是驱动器名称的范例:   D:   partition_name   以分区名称表示的待删除分区。可代替 drive_name 使用。仅与 /delete 同时使用。以下是分区名称的范例:   DeviceHardDisk0Partition1    大小   要创建的分区大小,以兆字节 (MB)表示。仅与 /add 同时使用。   范例   下例将删除分区: diskpart /delete Device HardDisk0 Partition3 diskpart /delete F:   下例将在硬盘上添加一个 20 MB 的分区:   diskpart /add Device HardDisk0 20   Fixboot

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧