玩玩vector

转自:http://blog.youkuaiyun.com/norains/archive/2008/05/10/2431642.aspx

 

//========================================================================
//TITLE:
//    玩玩vector
//AUTHOR:
//    norains
//DATE:
//    Saturday  10-May-2008
//Environment:
//    VS2005 + MIPS-SDK
//========================================================================

    本文不是讨论为什么要用vector替代数组,或是为什么一定要使用vector,而是在如何用vector在一些场合起到有意思的运用。本文所讨论的方式,并不是建立于推荐的原则,而仅仅是展示vector的有趣用法。在实际中是否使用,可各自掌握。
   
    1.内存动态分配
   
    最常常用的场合,vector其实也是为此而诞生的。举个很简单的例子:
   
    普通代码:
    #define NEW_SIZE  10
    int *pArr = new int[NEW_SIZE];
    ...
    delete []pArr;
   
    vector替代代码:
    std::vector<int> vct;
    vct.resize(NEW_SIZE);
   
    好处不言而喻,采用new分配内存的话,还需要调用delete来负责释放;而如果采用vector,那么,只要分配就好。释放?不管,就让编译器操心吧!
   
   
    2.存储字符串
   
    既然数组能存储字符串,那么vector自然也不甘落后咯。
   
    普通代码:
    WCHAR szPath[MAX_PATH];
    wcscpy(szPath,L"path");
   
    vector替代代码:
    std::vector<WCHAR> vctPath(MAX_PATH);
    wcscpy(&vctPath[0],L"path");
   
    在这里我们需要注意一点,标准C++中规定,vector的数据保存是必须在一段连续的内存中,所以我们在函数中可以使用&vctPath[0]的方式。注意,这里还有一个[0]下标,因为如果没有该下标,而仅仅是&vctPath,那么该地址只是对象的起始地址,而不是数据存储的起始地址。对于wcscpy函数来说,它的目标地址必须为一块连续的数据存储内存,而&vctPath[0]刚好符合。
   
    由此我们可以得出一个结论,凡是需要传递数组起始地址的场合,如果使用vector,那么都可以采用&vector[0]的方式替代。
   
   
    3.存储内存数据
   
    其实这部份内容和第2点差不多,vector既然能存储字符串,那么铁定也能存储内存的数据。
   
    普通代码:
    #define MEM_SIZE  20
    BYTE * pMem = malloc(MEM_SIZE);
    ...
    free(pMem);
   
    vector替代代码:
    std::vector<BYTE> vct;
    vct.resize(MEM_SIZE);
   
    在使用内存处理函数时只要采用和第二点相同的方式即可:
    memcpy(&vct[0],pBuf,20);
   
    不过本节的重点不在于如何存储内存数据,因为这可以通过第1、2点可以推断出来,而是想说明另外一个问题,采用vector可能可以起到简化函数行参的作用。
   
    举个例子,我们实际想写一个函数,需要转换pSource指向的内存数据,那么我们的这个函数至少需要两个参数,分别是指向分配的内存,以及该内存区域的大小:
    void Convert(BYTE * pBuf, ULONG ulSize)
    {
      for(int i = 0; i < ulSize; i ++)
      {
      ...
      }
    }
   
    但如果是用vector作为形参,由于vector可以调用size()函数获取长度,所以可以减少一个形参个数:
    void Convert(std::vector<BYTE> &vect)
    {
     for(std::vector<BYTE>::size_type i = 0; i < vect.size(); i ++)
       {
       ...
       }
    }
   
   
    4.vector的一个应用示例
   
    在文章的最后,举一个vector可以简化设计的例子。
   
    如果我们需要设计这么一个函数,输入班级的序号,然后返回班里每个人的成绩。
   
    因为需要存储每个人的成绩,所以采用数组来存储应该是一个很合理的选择。又因为每个班级的人数不一致,所以我们必须采用动态分配数组的方式:
   
    int * GetScore(int iIndexClass,int *pLen)
    {
      ...
     
      int *pNew = new int[iAmount_cls_1];
      *pLen = iAmount_cls_1;
      ...
     
      return pNew;
    }
   
    这会引发一个问题,首先我们需要增加一个形参,用来指示该数组的长度。当然,这还是其次,最重要的是,因为内存是动态分配的,需要手工释放。问题就出来了,内存的分配是函数内部分配,而释放需要调用者手工释放!万一调用者忘记释放了呢?最好的结果无非是内存慢慢被侵蚀,然后出现异常。而调用者如果记得释放呢?是不是就没问题了呢?错!在例子中,调用者应该是需要调用delete来释放内存;而如果万一某一天,GetScore函数的编写者不采用new方式,而是malloc,那么调用者调用delete释放内存会出现什么结果?喔,我也不知道,因为C++中未定义。
   
    似乎使用数组让我们走入了个两难的境地。那么,如果使用vector呢?
   
    函数如下:
       
    std::vector<int> GetScore(int iIndexClass)
    {
      ...
    
     vector<int> vct(iAmount_cls_1);
   
      ...
     
      return vct;
    }
   
    使用就非常简单咯:
    vector<int> vctScore;
    vctScore = GetScore(1);
   
    不用手工释放内存,不用增加多余的指示长度参数(因为可以调用vctScore.size()来获取),一切都那么简单,一切都那么美好,难道不是么?

发表于 @ 2008年05月10日 23:52:23|评论(2 )

新一篇: AU1200 GPIO的使用 | 旧一篇: 喘气

hkooyu 发表于2008年6月1日 23:06:36   IP: 举报
std::vector<int> GetScore(int iIndexClass)
{
...

vector<int> vct(iAmount_cls_1);

...

return vct;
}

vct会不会被析构?
norains 发表于2008年6月2日 9:24:12   IP: 举报
Re hkooyu: 你可以将这个函数类比于:int GetSCore(int iIndexClass){... int i;...return i;} 这样应该能解决你的疑惑吧? :-)
flushtime 发表于2008年7月5日 9:36:57   IP:202.113.19.* 举报
vct会被析构,但析构前会得到vct的一个拷贝。
### 技术实现与游戏发 线上电玩的技术实现涉及多个方面,包括前端和后端的发、数据库设计、用户界面设计以及网络通信等。以下是具体的实现步骤和技术要点: #### 1. 前端发 前端发主要负责用户界面的设计和实现。通常使用HTML、CSS和JavaScript进行发,结合框架如React或Vue.js可以提高发效率和用户体验。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>线上电玩城</title> <style> body { font-family: Arial, sans-serif; } .game-container { display: flex; flex-wrap: wrap; justify-content: center; } .game-card { border: 1px solid #ccc; margin: 10px; padding: 10px; width: 200px; } </style> </head> <body> <h1>欢迎来到线上电玩城</h1> <div class="game-container"> <div class="game-card"> <h2>游戏名称</h2> <p>游戏描述</p> </div> <!-- 更多游戏卡片 --> </div> <script src="app.js"></script> </body> </html> ``` #### 2. 后端发 后端发负责处理业务逻辑、数据存储和API接口的设计。常用的后端语言有Node.js、Python(Django/Flask)、Java(Spring Boot)等。以下是一个简单的Node.js示例: ```javascript const express = require('express'); const app = express(); const port = 3000; app.get('/api/games', (req, res) => { const games = [ { id: 1, name: '游戏1', description: '这是一个经典的游戏' }, { id: 2, name: '游戏2', description: '这是一个新的游戏' } ]; res.json(games); }); app.listen(port, () => { console.log(`服务器运行在 http://localhost:${port}`); }); ``` #### 3. 数据库设计 数据库设计是线上电玩的重要组成部分,用于存储用户信息、游戏数据、交易记录等。常用的关系型数据库有MySQL、PostgreSQL,非关系型数据库有MongoDB等。 ```sql CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, password VARCHAR(100) NOT NULL ); CREATE TABLE games ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, description TEXT ); CREATE TABLE transactions ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT, game_id INT, amount DECIMAL(10, 2), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (game_id) REFERENCES games(id) ); ``` #### 4. 游戏发 游戏发涉及游戏引擎的选择和使用。常见的游戏引擎有Unity、Unreal Engine等。Unity适合2D和3D游戏发,支持多种平台;Unreal Engine适合高质量的3D游戏发。 ```csharp // Unity C# 脚本示例 using UnityEngine; public class PlayerController : MonoBehaviour { public float speed = 5.0f; void Update() { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); transform.Translate(movement * speed * Time.deltaTime); } } ``` #### 5. 网络通信 网络通信是线上电玩的关键部分,确保玩家之间的实时互动。WebSocket协议常用于实现实时通信,Socket.IO是一个流行的库。 ```javascript // 客户端代码 const socket = io('http://localhost:3000'); socket.on('connect', () => { console.log('连接成功'); }); socket.on('gameUpdate', (data) => { console.log('游戏更新:', data); }); // 服务端代码 const io = require('socket.io')(3000); io.on('connection', (socket) => { console.log('新用户连接'); socket.on('disconnect', () => { console.log('用户断连接'); }); socket.on('playerMove', (data) => { io.emit('gameUpdate', data); }); }); ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值