问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

new有几种用法?

发布网友 发布时间:2022-04-21 07:55

我来回答

4个回答

懂视网 时间:2022-04-30 04:29

一 建立软件框架

这里的框架指的是让软件运行起来的那种框架,因为我需要让成品不依赖NewLisp的东西,自己就能运行,也就是说编译成可执行程序。

这在主流静态语言中易如反掌的事,在Lisp系列语言中简直比登天还难,只有极少的一星半点的Lisp方言实现能支持,而且效果还不好。以至于新的Lisp方言实现干脆直接挂上JVM平台了,比如Clojure。

而NewLisp是我遇到的最强大的Lisp方言实现,因为我可以像喝水一样极其轻易的编译可执行程序,而且没有任何负面的问题存在。NewLisp编译的原理非常简单,就是复制自身,然后在后面加上代码,这样一个可执行程序就出来了。

; hello.lisp
(print "hello world!
")
(exit) 
>newlisp -x hello.lisp hello.exe
>hello.exe
hello world!
>_

当然直接在发行版中附带newlisp.exe,然后用newlisp main.lisp一样可以,但这并不好。编译后的程序不需要额外的命令启动,而且不会被newlisp原本的参数所干扰,这是很重要的一点。

但是这有一个缺点,就是NewLisp只能编译单个lisp文件为可执行程序,至少我目前没有发现编译多个文件的方法。不过这个缺点很容易破解,而且其并不算缺点。我们只需要建立一个框架就可以了:

 ; main.lisp
(load "a.lisp")
(load "b.lisp")
...
(exit (app:run (rest (main-args))))

这样就做出了一个框架,启动时加载模块,然后用app:run来开始执行,app:run定义在某个模块中,作为程序入口。这样,我们就只需要编译main.lisp:newlisp -x main.lisp demo.exe,然而将所有模块放在demo.exe的目录中,这些模块可随时修改。

但是这样就行了吗?当然不行,因为这是硬编码,所以,我们需要考虑更好的设计。我最终决定使用二级指针来完成,于是整个框架只需要两行代码:

; main.lisp
(load "app.lisp") ; 加载一级指针,通过这个模块加载其他模块
(exit (app:run (rest (main-args))))

其中app.lisp就是一级指针,也可以说是模块加载器:

; app.lisp
(load "a.lisp")
(load "b.lisp")
(load "c.lisp")
...

在app.lisp中加载需要的模块,也可以同时做一些事务,或者是定义一些东西等等。这样,除了app.lisp这个文件的文件名不能修改,其他的都可以随意修改,想加模块随意加,想修改模块随意改。

 

二 软件定义

首先我对sdb的定义是一个简单的Key-Value数据库系统,而且是面向本地的。所以我决定像SQLite一样,一个文件对应一个数据库。既然是Key-Value数据库,那么就需要定义好模型。

一个数据库中,平淡的存储Pair就完事了吗,不,我需要个性一点。所以我在Pair的上面加了一层:空间。

一个数据库中可以用多个空间,Pair存储在空间之中。这看起来就像是所有表都只有2列的SQL数据库。

然后是如何操作数据库,我决定采用最简单的方法,因为这本来就只是练手之作。使用一个REPL客户端,通过执行用户的命令来处理事务。当然这个不会有SQL的那些东西,采用最简单的命令结构:

// 设想
>get a.p // 获取空间a中key为p的Pair的值
...
>set a.p 100 // 更新空间a中key为p的Pair的值或建立新的Pair
...

最核心的两个命令:get、set。作为一个Key-Value数据库来说,是核心的东西了。

这几乎就说明了需要做什么了,提供一个REPL客户端,用户通过命令来处理事务,那么设计好对这些命令的处理就差不多是做好sdb了。

以下是目前定义的所有命令:

get <spacename>.<key>                     // 获取值
set <spacename>.<key> <value>             // 更新值或建立Pair
list <spacename>                          // 列出一个空间中的所有Pair
erase <spacename>.<key> ...               // 删除所有指定的Pair
eraseall <spacename> ...                  // 删除所有指定的空间中的所有Pair
spaces                                    // 列出所有空间
dup <source-spacename> <new-spacename>    // 复制一个空间到一个新的空间
new <spacename> ...                       // 建立一至多个空间
delete <spacename> ...                    // 删除所有指定的空间
link <file>                               // 连接到一个数据库文件
unlink                                    // 断开当前连接并保存更新
relink                                    // 断开当前连接,仅重置
h or help <command>                       // 显示命令帮助信息
q or quit                                 // 退出sdb,自动保存更新
q! or quit!                               // 仅退出sdb

然后是sdb的程序参数,目前倒没什么可定义的,所以只有两个:

link:<file>        启动时连接到一个数据库文件
help               显示使用帮助信息

例子:

sdb                     // 直接进入REPL
sdb help                // 显示使用帮助信息,虽然你已经知道了
sdb link:db.txt         // 启动时连接数据库文件db.txt

 

三 模块划分

sdb本身是一个Key-Value数据库系统,同时提供REPL客户端,那么我们就划分两个模块,一个是客户端模块,一个是数据库模块。客户端模块处理用户输入,调用数据库模块来处理事务并输出结果,数据库模块负责数据模型和文件存储。

于是sdb需要2个模块,总共4个代码文件:

sdb/
  app.lisp       ; 一级指针,模块加载器
  client.lisp    ; 客户端模块
  db.lisp        ; 数据库模块
  main.lisp      ; 软件框架
; main.lisp
(load "app.lisp")
(exit (app:run (rest (main-args))))
; app.lisp
(load "db.lisp")
(load "client.lisp")
; db.lisp
(context ‘db)
...
(context ‘MAIN)
; client.lisp
(context ‘app)
...
(define run
  (lambda (.args)
    ))
(context ‘MAIN)

在NewLisp中定义模块很简单,使用(context)函数就行了,(context)会建立一个模块,或者切换到已有的模块,访问一个模块的东西时,需要用<模块名>:<符号名>,就比如app:run,就是访问app模块中的run,从而调用该函数。每个模块开始和结尾都调用了一次(context)函数,这是一种模块设计方式。第一次是建立模块,第二次是切换到顶层作用域。在这里,main.lisp是框架,app.lisp是加载器,所以不需要定义成模块。

 

四 客户端模块

client.lisp主要负责处理用户的输入,并调用db.lisp来处理事务,然后输出结果,不断的循环,直到用户砸了机器为止。当然肯定不需要砸机器,这是一个标准的Read->Exec->Print->Loop循环,我们已经提供了quit/quit!两个命令让用户能退出。在框架中,已经预先限定了,需要app模块中有个run函数,这将作为程序的入口。简单起见,直接在run中做好REPL循环,顺带检查参数。

(define run
  (lambda (.args)
    ; 如果有参数,调用do-options解析并处理
    (unless (empty? .args) (do-options .args))
    ; 显示软件标题
    (show-title)
    ; 是否要继续循环,是就继续
    (while (nextrun?)
      ; 显示当前上下文环境 (连接的数据库)
      (echo-context)
      ; 等待用户输入然后处理
      (query (read-line)))
    0))

从代码已经可以清晰的看出整个流程了,但是你可能觉得这个(nextrun?)是不是多余呢,其实不多余。因为整个调用链不小,为了确保正确性,所以使用了一个全局变量。当然这是安全的,因为读写是通过专用函数操作的:

(define _isnextrun true) ; 一种命名风格,前面加_表示为模块内部符号
(define nextrun?
  (lambda ()
    _isnextrun))
(define stoprun
  (lambda ()
    (setf _isnextrun false)))

query函数主要负责解析命令、检查命令,执行命令:

(define query
  (lambda (txt)
    (letn ((tokens (get-tokens txt)) ; 解析命令文本,转换成单词列表
          (cmd (cmd-prehead (first tokens))) ; 是什么命令
          (cmdargs (rest tokens))) ; 这个命令的参数列表
      (case cmd
        ; 由于细节较多,所以部分命令的处理过程省略
        ("get" ...)
        ("set" ...)
        ("list" ...)
        ("erase" ...)
        ("eraseall" ...)
        ("spaces" (map println (db:list-spaces)))
        ("dup" ...)
        ("new" ...)
        ("delete" ...)
        ("link" ...)
        ("unlink" (cmd-request (db:unlink)))
        ("relink" (cmd-request (db:relink)))
        ("help" (cmd-help cmdargs))
        ("quit"
          (begin
            (db:unlink)
            (stoprun)))
        ("quit!" (stoprun))
        (true
          (unless (empty? cmd)
            (println "Unknow command, enter h or help see more Information.")))))))

(cmd-request)是对一次数据库操作的过程封装:

(define cmd-request
  (lambda (result)
    (if result
      (println "ok")                      ; 操作成功,显示ok
      (println (db:get-last-error)))))    ; 失败,显示错误信息

(cmd-prehead)是对命令的预处理:

(define cmd-prehead
  (lambda (txt)
    (let ((cmd (lower-case txt))) ; 转换成小写
      (case cmd
        ("h"    "help")      ; h替换成help
        ("q"    "quit")      ; q替换成quit
        ("q!"   "quit!")     ; q!替换成quit!
        (true cmd)))))       ; 其他的返回自身

基本上这就是client.lisp的全部了,其他未列出来的东西无关紧要。

 

五 数据库模块

在db.lisp中,最核心的问题就是,如何表示数据模型,使用什么结构来构造数据,也可以说是,怎么设计get/set函数。只要get/set设计好了,其他的全部就不是问题了。

如果只是纯粹的Key-Values,那么直接用一个列表就行了,NewLisp有着原生的支持来构造Key-Value表:

> (setf x ‘())
()
> (push ‘("a" 1) x)                 // 建立键值对
(("a" 1))
> (push ‘("b" 2) x) -1)
(("a" 1) ("b" 2))
> (assoc "a" x)                     // 查询键值对
("a" 1)
> (setf (assoc "a" x) ‘("a" "one")) // 更新键值对
("a" "one")
> (pop-assoc "a")                   // 删除键值对
("b" 2)
> x
(("a" "one"))

对于每一个空间,使用原生提供的push/assoc/pop-assoc就可以完成全部的键值对操作了。但是一个数据库有多个空间,那么这些空间怎么放呢?直接嵌套Key-Value表吗?

‘(("s1"           // 空间s1,有a=1, b=2两个键值对
    (("a" 1)
     ("b" 2)))
  ("s2"           // 空间s2,有c=1, d=2两个键值对
    (("c" 1)
     ("d" 2)))
  ("s3"           // 空间s3,有e=1, f=2两个键值对
    (("e" 1)
     ("f" 2))))

这样,访问一个键值对就需要如下形式:

(assoc "a" (last (assoc "s1" _spaces)))      ; 访问空间s1中的a
...
(map (lambda (s) (first s)) _spaces)         ; 列出所有空间的名称

对我来说,这样不好,还有一个问题是,更新一个空间中的键值对时,需要(setf (assoc spacename _spaces) newspace)。这意味每一次对空间里键值对的增/删/改操作,都会生成一个新的空间。

在尝试这样设计get/set之后,我决定放弃这种结构,而使用另一种方式。

这种方式很不直接,但很有效。具体的做法是,让每一个空间都对应着一个符号,建立空间时生成一个符号和一个空间对象(Key-Value表),让这个符号指向空间对象,删除一个空间时,直接删除对应的符号就可以了。

这是什么意思呢?就是相当于在运行时定义变量,这个变量的名称都是临时生成的。经过一番设计,最终的结构如下:

(define _spaces ‘())

你没看错,就只是定义一个列表,_spaces中只存放空间的名称。那么如何建立空间呢?建立的空间要怎么访问呢?

(define new-space
  (lambda (name)
    (if (have-space? name)                   ; 这个空间已经存在了吗?
      (ERROR _SPACE_HAS_EXIST name)          ; 已经有了,不能重复建立
      (begin                                 ; 如果还未存在
        (set (get-space-symbol name) ‘())    ; 定义一个符号,符号的名称根据这个空间的名称来生成,指向一个空的Key-Value表
        (push name _spaces)))))              ; 加入这个空间的名称

是不是有点困惑,为什么这样就建立了一个空间呢?让我们再看下(get-space-symbol)

(define get-space-symbol
  (lambda (name)
    (sym (string "_space." name))))          ; 返回一个符号,这个符号的名称为_space.加上空间的名称

就比如刚才示范的三个空间,一一建立的话,就会在NewLisp的运行时环境中,定义三个新的符号,这些符号指向各自的Key-Value表。

于是,就可以在代码中使用(setf (assoc keyname (get-space-symbol spacename)) (list keyname value))之类的形式来增/删/改一个空间的键值对。

每一次建立空间都会生成一个新的符号,但我们并不能预先知道这个符号是什么名称。上面三个空间在建立时生成_space.s1、_space.s2、_space.s3三个符号,但我们无法直接使用,所以我们需要(eval)来完成对空间的访问。这样的结构,使得get/set也轻松的设计出来:

(define kvs-get
  (lambda (spacename keyname)
    (if (have-space? spacename)                              ; 这个空间存在吗?
      (let ((kv                                              ; 如果存在
            (eval                                            ; 生成[获取键值对的函数调用] 并执行
              (list
                ‘assoc
                ‘keyname
                (get-space-symbol spacename)))))
        (if kv                                               ; 这个键值对存在吗?
          (last kv)                                          ; 存在,返回值
          (ERROR _PAIR_NO_IN_SPACE keyname spacename)))      ; 不存在,提供错误信息
      (ERROR _SPACE_NO_EXIST spacename))))                   ; 这个空间不存在,提供错误信息

(define kvs-set
  (lambda (spacename keyname value)
    (if (have-space? spacename)                              ; 这个空间存在吗?
      (begin                                                 ; 如果存在
        (eval (list                                          ; 生成[删除这个键值对的函数调用] 并执行
          ‘pop-assoc
          ‘keyname
          (get-space-symbol spacename)))
        (eval (list                                          ; 生成[加入新键值对的函数调用] 并执行
          ‘push
          ‘(list keyname value)
          (get-space-symbol spacename))))
      (ERROR _SPACE_NO_EXIST spacename))))                   ; 这个空间不存在,提供错误信息

为什么需要eval呢?因为我们需要访问一个运行时建立的符号,就比如:

var x = 100;

我们可以在源代码中直接对x进行任何操作,但是如果这个x是运行时定义的呢?为什么要运行时定义,因为我们不知道用户会用什么名称来建立空间,我们需要将运行时建立的符号,融合进平常的操作中:

(eval (list assoc ‘keyname (get-space-symbol spacename))) 
; 如果spacename传入的是s1
; 那么就会生成这样的函数调用:
(assoc keyname _space.s1)
; 看到这里应该所有人都明白了

为什么这么麻烦?因为NewLisp没有提供指针变量的支持,如果能用指针,就能有更简单好用的设计。这是Lisp的缺点之一,主要是因为很多方言实现都避免指针导致的。就像很多Lisp中易如反掌的事,在C这些语言中需要绕出病来一样,很多在C这些语言中易如反掌的事,同样在Lisp中会绕出病。

 


后记

就在这时,我发现这样的一个提示:当前已输入9840个字符, 您还可以输入160个字符。于是我只好草草结束。但还好的是,这个sdb最关键的几个地方都讲解了一遍。

当然这里讲解比较浅显,具体的东西,还是要看代码才会明白。文章写的这么多字,远不如直接看代码来的清晰。

NewLisp是一个很有价值的Lisp方言实现,虽然目前还有很多缺点。

您还可以输入3个.

使用NewLisp设计Key-Value数据库系统

标签:

热心网友 时间:2022-04-30 01:37

1、开辟单变量地址空间

new int;  //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a. 2)int *a = new int(5) 作用同上,但是同时将整数赋值为5。

2、开辟数组空间

要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问。用new可以动态开辟,撤销地址空间。在编程序时,若用完一个变量,下次需要再用,可以在每次开始使用时开辟一个空间,在用完后撤销它。

扩展资料:

定位放置new的作用:

1、在 C++ 中,通过 new 运算符来实现动态内存分配。new操作符从自由存储区(free store)上为对象动态分配内存空间,凡是通过new操作符进行内存申请,该内存即为自由存储区。

2、new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。

3、new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。


参考资料来源:

百度百科-定位放置new

热心网友 时间:2022-04-30 02:55

"1.
new()
分配这种类型的1个大小的内存空间,并以括号中的值来初始化这个变量;
2.
new[]
分配这种类型的n个大小的内存空间,并用默认构造函数来初始化这类变量;
#include<iostream>
#include<cstring>
using
namespace
std;
int
main(){
//char*
p=new
char("Hello");
//error分配1个char(1字节)的空间,
//用"Hello"来初始化,这明显不对
char*
p=new
char[6];
//p="Hello";
//不能将字符串直接赋值给该字符指针p,原因是:
//指针p指向的是字符串的第1个字符,只可以用下边的
//strcpy
strcpy(p,"Hello");
cout<<*p<<endl;
//只是输出p指向的字符串的第1个字符!
cout<<p<<endl;
//输出p指向的字符串!
delete[]
p;
return
0;}
输出结果:
H
Hello
3.
当用new运算符定义1个*数组变量或数组对象时,它产生1个指向数组第1个元素的指针,返回的类型保持了除最左边维数外的全部维数。例如:
int
*p1
=
new
int[10];
返回的是1个指向int的指针int*
int
(*p2)[10]
=
new
int[2][10];
new了1个二维数组,
去掉最左边那一维[2],
剩下int[10],
因此返回的是1个指向int[10]这种一维数组的指针int
(*)[10].
int
(*p3)[2][10]
=
new
int[5][2][10];
new了1个三维数组,
去掉最左边那一维[5],
还有int[2][10],
因此返回的是1个指向二维数组int[2][10]这种类型的指针int
(*)[2][10].
#include<iostream>
#include
<typeinfo>
using
namespace
std;
int
main()
{
int
*a
=
new
int[34];
int
*b
=
new
int[];
int
(*c)[2]
=
new
int[34][2];
int
(*d)[2]
=
new
int[][2];
int
(*e)[2][3]
=
new
int[34][2][3];
int
(*f)[2][3]
=
new
int[][2][3];
a[0]
=
1;
b[0]
=
1;
//运行时错误,无分配的内存,b只起指针的作用,用来指向相应的数据
c[0][0]
=
1;
d[0][0]
=
1;//运行时错误,无分配的内存,d只起指针的作用,用来指向相应的数据
e[0][0][0]
=
1;
f[0][0][0]
=
1;//运行时错误,无分配的内存,f只起指针的作用,用来指向相应的数据
cout<<typeid(a).name()<<endl;
cout<<typeid(b).name()<<endl;
cout<<typeid(c).name()<<endl;
cout<<typeid(d).name()<<endl;
cout<<typeid(e).name()<<endl;
cout<<typeid(f).name()<<endl;
delete[]
a;
delete[]
b;
delete[]
c;
delete[]
d;
delete[]
e;
delete[]
f;
}
输出结果:
int
*
int
*
int
(*)[2]
int
(*)[2]
int
(*)[2][3]
int
(*)[2][3]
虽然有三种new的用法,可是分为两大类也未尝不可,那么是哪两类呢?其一是new
operator,也叫new表达式;其二是operator
new,也叫new操作符。这2个英文名称起的也太绝了,很容易搞混,那就记中文名称吧。new表达式比较常见,也最常用,例如:
string*
ps
=
new
string("abc");
上边这个new表达式完成了两件事情:申请内存和初始化对象。
new操作符类似于C语言中的malloc,只是负责申请内存,例如:
void*
buffer
=
operator
new(sizeof(string));
注意这里多了1个operator。这是new的第二个用法,也算比较常见吧。
那么第三个用法就不很常见了,官方的说法是placement
new,它用于在给定的内存中初始化对象,也就是说你手中已有一块闲置的内存,例如:
void*
buffer
=
operator
new(sizeof(string));
//那么目前buffer是你所拥有闲置内存的指针
buffer
=
new(buffer)
string("abc");
//调出使用了placement
new,在buffer所指向的内存中初始化string类型的对象,初始值是"abc"
事实上,placement
new也是new表达式的一种,可是比普通的new表达式多了1个参数,当然完成的操作和返回值也不一样。
因此上边new的第一种用法可以分解2个动作,分别为后面的两种用法。"

热心网友 时间:2022-04-30 04:29

1. new() 分配这种类型的一个大小的内存空间,并以括号中的值来初始化这个变量;

2. new[] 分配这种类型的n个大小的内存空间,并用默认构造函数来初始化这些变量;

#include<iostream>

#include<cstring>

using namespace std;

int main(){

//char* p=new char("Hello");

//error分配一个char(1字节)的空间,

//用"Hello"来初始化,这明显不对

char* p=new char[6];

//p="Hello";

//不能将字符串直接赋值给该字符指针p,原因是:

//指针p指向的是字符串的第一个字符,只能用下面的

//strcpy

strcpy(p,"Hello");

cout<<*p<<endl; //只是输出p指向的字符串的第一个字符!

cout<<p<<endl; //输出p指向的字符串!

delete[] p;

return 0;}

输出结果:

H

Hello

3. 当使用new运算符定义一个*数组变量或数组对象时,它产生一个指向数组第一个元素的指针,返回的类型保持了除最左边维数外的所有维数。例如:

int *p1 = new int[10];

返回的是一个指向int的指针int*

int (*p2)[10] = new int[2][10];

new了一个二维数组, 去掉最左边那一维[2], 剩下int[10], 所以返回的是一个指向int[10]这种一维数组的指针int (*)[10].

int (*p3)[2][10] = new int[5][2][10]; new了一个三维数组, 去掉最左边那一维[5], 还有int[2][10], 所以返回的是一个指向二维数组int[2][10]这种类型的指针int (*)[2][10].

#include<iostream>

#include <typeinfo>

using namespace std;

int main() {

int *a = new int[34];

int *b = new int[];

int (*c)[2] = new

int[34][2];

int (*d)[2] = new int[][2];

int (*e)[2][3] = new int[34][2][3];

int (*f)[2][3] = new int[][2][3];

a[0] = 1;

b[0] = 1; //运行时错误,无分配的内存,b只起指针的作用,用来指向相应的数据

c[0][0] = 1;

d[0][0] = 1;//运行时错误,无分配的内存,d只起指针的作用,用来指向相应的数据

e[0][0][0] = 1;

f[0][0][0] = 1;//运行时错误,无分配的内存,f只起指针的作用,用来指向相应的数据

cout<<typeid(a).name()<<endl;

cout<<typeid(b).name()<<endl;

cout<<typeid(c).name()<<endl;

cout<<typeid(d).name()<<endl;

cout<<typeid(e).name()<<endl;

cout<<typeid(f).name()<<endl;

delete[] a; delete[] b; delete[] c;

delete[] d; delete[] e; delete[] f;

}

输出结果:

int *

int *

int (*)[2]

int (*)[2]

int (*)[2][3]

int (*)[2][3]

虽然有三种new的用法,但是分为两大类也未尝不可,那么是哪两类呢?其一是new operator,也叫new表达式;其二是operator new,也叫new操作符。这两个英文名称起的也太绝了,很容易搞混,那就记中文名称吧。new表达式比较常见,也最常用,例如:
string* ps = new string("abc");
上面这个new表达式完成了两件事情:申请内存和初始化对象。
new操作符类似于C语言中的malloc,只是负责申请内存,例如:
void* buffer = operator new(sizeof(string));
注意这里多了一个operator。这是new的第二个用法,也算比较常见吧。
那么第三个用法就不很常见了,官方的说法是placement new,它用于在给定的内存中初始化对象,也就是说你手中已有一块闲置的内存,例如:
void* buffer = operator new(sizeof(string));
//那么现在buffer是你所拥有闲置内存的指针
buffer = new(buffer) string("abc"); //调用了placement new,在buffer所指向的内存中初始化string类型的对象,初始值是"abc"
事实上,placement new也是new表达式的一种,但是比普通的new表达式多了一个参数,当然完成的操作和返回值也不同。
因此上面new的第一种用法可以分解两个动作,分别为后面的两种用法。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
苹果电脑电池充不进电苹果电脑充不进去电是怎么回事 苹果电脑不充电没反应苹果电脑充电指示灯不亮充不了电怎么办 狗狗更加忠诚护家、善解人意,养一只宠物陪伴自己,泰迪能长多大... 描写泰迪狗的外形和特点的句子 国外留学有用吗 花钱出国留学有用吗 !这叫什么号 百万医疗赔付后是否可以续保 前一年理赔过医疗险还能续保吗? 医疗住院险理赔后还能购买吗? C++中,new/delete和malloc/free的区别 java中new具体是干吗的? C++ 定位new 的问题 关于数组的new和delete的比较底层的问题 C语言中的malloc和C++中new的区别 malloc和new的区别是什么? C++中的new是如何实现的 VC++的编译器中,运算符new底层的实现是什么? 觉得有些人家 家庭收入也不高呀 但是他们特别舍得花钱的 吃啊穿啊都还挺讲究的 名牌什么的 怎么回... 刺激战场枪械的伤害排名是怎样的? 和平精英:你认为哪些步枪非常好用且实在? 和平精英即将上线2款枪械,这两款枪械有什么特点? 刺激战场什么枪好用?求推荐。 手机淘宝实物专享红包是免费领取的吗? 淘宝的红包是免费领取的吗 什么软件可以领qq红包 微信哪里可以免费抢红包,有每天都可以抢的吗? 如何免费领取美团红包? 怎么样做微信表情包? 如何把在迷你世界里录的录相保存到相册? 继承和new实例化的问题 直接赋值字符串和new有什么区别? java里的new到底是什么意思??? 一个关于c++中new的小问题 java代码:new 类名(){方法定义}应该如何理解? Java中String直接赋值和使用new的区别 Java用接口new实现类和实现类new实现类的区别 C#中的new实例化有什么作用 小米2s充电器参数 java 关于new的用法 求大神 C语言中new的用法 我以前用uc注册的微博现在登陆不了了 可以帮我找回吗 UC注册的新浪微博如何找回 我用UC注册的新浪微博忘记密码和登陆名了,怎么找回来 2011年的时候用UC浏览器注册的新浪微博。现在手机换了。那个账户也登录不了了。 以前用UC浏览器的帐号注册了新浪微博,现在忘了邮箱和手机号也注销了,只记得昵称,要怎 么登录? UC帐号绑定微博找回的问题 换了浏览器怎么找回以前那个新浪微博账号?? 404 Not Found 手机uc浏览器上面的微博账号和密码忘记了怎么办啊