`
chelsea
  • 浏览: 119404 次
  • 来自: ...
社区版块
存档分类
最新评论

对象语义与值语义

    博客分类:
 
阅读更多

一、值语义

  • 所谓值语义是一个对象被系统标准的复制方式复制后,与被复制的对象之间毫无关系,可以彼此独立改变互不影响

实现

<!-- MSTableType="nolayout" -->

 

C++

Java

标准复制方式

赋值、拷贝构造

赋值,clone()

基本数据类型

包括整数,浮点数,布尔值,字符,指针等,全部为值语义

包括整数,浮点数,布尔值,字符等,全部为值语义

自定义类型

不包含资源的自定义类型,系统提供的缺省拷贝构造函数与赋值操作符亦保证了值语义;包含资源的自定义类型,需要提供深拷贝操作的拷贝构造函数和赋值操作符,并在构造函数中获取资源,在析构函数中释放资源

没有十分自然的方式将Java对象实现为值语义,通常采用“不可变类”的方式,如String,或递归实现深度clone()

优点

  • 避免别名问题导致的意外修改

  • 避免对共享资源的引用引起的释放时机和额外的引用计数问题

缺点

  • 占用较多内存

应用

  • 通常将具有“等价性”的对象实现为值语义,如Money,你的10块钱跟我的10块钱没什么两样,完全可以换过来用

举例

C++

Java

vector<int> first;

vector<int> second = first;

second.push_back(1000);

cout << first.size(); //0

cout << second.size();//1

String first = "abc";

String second = first;

first = first.replace('a', 'x');

System.out.println(first); //xbc

System.out.println(second);//abc

 

二、对象语义

  • 也叫指针语义,引用语义等,通常是指一个对象被系统标准的复制方式复制后,与被复制的对象之间依然共享底层资源,对任何一个的改变都将改变另一个

实现

 

C++

Java

标准复制方式

赋值、拷贝构造

赋值,clone()

自定义类型

包含资源的自定义类型,没有提供拷贝构造函数和赋值操作符,或者在拷贝构造函数和赋值操作符中有意共享资源,则此时的对象具有指针语义

缺省全为指针语义,除非该类及其成员递归实现深度clone(),或实现为“不可变类”

优点

  • 占用较少内存

缺点

  • 别名问题导致的意外修改,尤其应主意用于模块间接口的参数和返回值

  • 资源释放的额外负担,通常是引用计数

应用

  • 通常将必须保持“同一性”的对象实现为对象语义,如帐户,虽然你的帐户和我的帐户此时都只剩100块钱了,但你的是你的,我的是我的,将来你发了财也只会存到你帐户上;具有“同一性”的对象通常在系统中有唯一ID,这类对象通常不可复制,因为复制没有现实意义,如网络端口,数据库链接

举例

C++

Java

vector<int> obj(2, 0);

vector<int>::iterator first = obj.begin();

vector<int>::iterator second = first;

cout << *first; //0

cout << *second;//0

*first = 1;

cout << *first; //1

cout << *second;//1

List<Integer> first = new ArrayList<Integer>();

List<Integer> second = first;

second.add(1000);

System.out.println(first.size()); //1

System.out.println(second.size());//1

 

注:

  1. 即使在具有垃圾回收的系统中,资源释放依然是个问题,因为资源不止内存,还有网络端口,数据库链接等

  2. 同一与等价的问题,可参见<<Structure and Interpretation of Computer Programs>>笔记

  3. 录一篇 wangtianxing 老师的观点,比我说的清楚有趣的多:

我认为“值”与“对象”的区分在设计和实现时具有非常重要的指导作用,
因此下面做一些说明。

“值”与“对象”类型之间并没有严格定义的区分。但通常可以观察到下列不同:

0. “值”是“死的”、“傻的”、“简单的”、“具体的”、“可复制的”,
“对象”是“活的”、“聪明的”、“复杂的”、“抽象的”、“不可复制的”。

这里的“复杂性”主要还是指行为的复杂性,而非结构的复杂性。例如,

list< map< vector<string>, deque< set<int> > > >

仍然是一个不折不扣的“值”类型。

这里我们不在哲学的路上走太远,还是看看下面更具体的一些特征吧。

1. “值”的成员函数(包括解构函数)都不是 virtual 的,不是设计来被继承的。
“对象”的解构函数是 virtual 的,而且通常还有其它的 virtual 成员函数,
是设计来被继承的,或继承了其他基类。

// value:
struct String {
// non-virtual destructor:
~String() { delete[] s_; }
private:
char* s_;
};

// string should not be public-ly inherited.

// object:
struct OutputDevice {
virtual ~OutputDevice();
virtual void output( char const* ) = 0;
};

struct ConsoleOutputDevice : OutputDevice {
// inherits virtual destructor,
// overrides virtual member function:
void output( char const* );
};

2. “对象”经常必须通过指针或引用来使用,“值”不一定需要。

::std::auto_ptr<OutputDevice> output( new ConsoleOutputDevice() );

void f( OutputDevice& dev )
{
// ...
dev.output( "blah blah/n" );
// ...
}

String s = "dsjflsdjflsjlf";
String t = "djslfdsjfsl";
s += t;

void g( String s ) // by-value is OK.
{
// ...
}

g( s );


3. “值”可以复制出任意多份等价物,是 Assignable, CopyConstructible 的
(C++标准里定义了Assignable, CopyConstructible 的具体含义)。
“对象”通常不是 Assignable 也不是 CopyConstructible 的,通常是被共享的
不是被复制的。 即使“对象”被“克隆”,“克隆”出来的对象与原对象也不是
完全等价的:相同的基因,不同的个体。

string s = "dsjlfsdjlfsdjlfsdjl";
string t;
t = s;
// the following two lines are equivalent:
cout << s;
cout << t;

auto_ptr<OutputDevice> dev1( new ConsoleOutputDevice(...) );
auto_ptr<OutputDevice> dev2( dev1.clone() );
// the following two lines are NOT equivalent:
dev1->output( "blah blah" );
dev2->output( "blah blah" );

这里,dev2 可能具有与 dev1 相同的位置、大小、权限等属性,但却是
完全不同的另一个窗口。

4. 对于“值”类型,应该严格保证 constness-correctness,对于“对象”类型,
通常不需要,甚至有些 'const' 是有害的。

// bad design of a value type:
struct Contact {
string address(); // non-const
};

void f( Contact const& contact )
{
cout << contact.address(); // won't compile.
}

// maybe bad design of an intelligent object type:
struct Robot {
string name( Object const& asker ) const // const!
{ return my_name; }
private:
string my_name;
};

由于 Robot 的智能,问他一次名字也可能要触发它内部状态的改变。
一般来说,我们不应该对一个复杂“对象”假设任何操作不改变其内部状态,
因此其界面上不应有 const 成员函数。 使用一个 const Robot
也是毫无意义的。如果你觉得 Robot 比较特殊,可以想想 const Database。

5. “值”是可以比较的,“对象”通常是不可比较的,要比较的话,
应该比较对象的地址,而不是内容。

根据“值”类型表达的概念的特点,比较关系运算可分为两个层次:

a 相等性比较:

bool operator == ( T const& ) const;
bool operator != ( T const& ) const
{ return ! operator == ( other ); }

而且 operator !=( other ) 必须等价于 ! operator == ( other ),
operator == () 必须是一个“等价关系”(equivalence relationship):
任给 T a, b, c:

(自反的) (a == a) => true.
(对称的) (a == b) => (b == a).
(传递的) (a == b && b == c) => (a == c).

对于一个类型 T 的两个对象 a, b,如果表达式 (a == b) 可以转换为
bool 类型,而且这个 operator == () 是 T 上的一个等价关系,那么
就说 T 是 EqualityComparable 的。

b 排序关系比较:

bool operator < ( T const& ) const;
bool operator > ( T const& other ) const
{ return other < *this; }
bool operator >= ( T const& other ) const
{ return ! operator < ( other ); }
bool operator <= ( T const& other ) const
{ return ! operator > ( other ); }

这些运算之间的关系必须满足上面给出的实现所表达的等价性。
(因此通常只实现 operator<(),然后从这里 copy 另外三个!)
operator <() 必须是 T 上的一个“严格弱序”
(strict weak ordering)关系:

任给 T a, b, c:

(irreflexive) (a < a) => false.
(transitive) (a < b && b < c) => (a < c).
(weak ordering)
定义 eqiv(a,b) = ! (a < b) && ! (b < a).
equiv(a,b) && equiv(b,c) => eqiv(a,c).

这样,operator<() 可以在 equiv 决定的 T 的等价类上定义一个全序
(total ordering).

对于一个类型 T 的两个对象 a, b,如果表达式 (a < b) 可以转换为
bool 类型,而且这个 operator < () 是 T 上的一个严格弱序关系,
那么就说 T 是 LessThanComparable 的。

一个“值”类型可以只实现相等性比较。如果同时实现了排序关系比较,
那么必须有 (a == b) iff (! (a < b) && ! (b < a))。

上述对关系运算的要求来自于 C++ 标准中对容器类中对象的要求。即使
你的类型的对象不被放到标准容器中,也应该满足上述要求,否则就可能
产生一些让他人吃惊的行为。

综上所述,在设计一个类时,如果思考一下这个类表达的是一个简单的“值”
还是一个复杂的“对象”,非常有助于决定类的界面以及用法的许多方面:

. 会不会被继承/有没有 virtual 函数?
. 是否允许拷贝和赋值?还是必须共享/克隆?
. 如何对待 constness-correctness?
. 是否应该实现比较运算?实现哪些?

等等等等。

(除了“值”和“对象”的区分外,还有一批C++中的类型可以归类为
表达了一个“概念”,但那是另一个话题)

"三月的外星人" <UFO@sina.com> 写入消息
news:a8g76p$cb14@svr.novel.com...
> 标准中一些具体的类是否都应当看作是“值”类,比如“map",list,vector等?
> 而一些抽象的类就可以看成是”对象“类?

标准的数据类型大致有以下几类:

“值”:

各种基本类型:int, double, ...。各种指针。complex<>。
各种容器: vector<>, list<>, multi/set<>, multi/map<>, deque<>,
bitset<>, basic_string<>, valarray<>... 以及它们的各种 iterator。
adaptors: stack<>, queue<>, priority_queue<>。
各种 functor: less, greater, equal_to, plus, minus, binder1st...。
locale 是把“对象”类型通过共享方式包装成“值”类型,以方便使用。


“对象”:

iostream相关类:basic_ios<>, basic_*stream<>, basic_*streambuf<>。
各种facet: ctype_base/ctype<>, codecvt_base/codecvt<>...。
type_info。


“值与对象的混合物”

异常类:exception,bad_exception, logic_error, range_error...。
可以象“值”一样复制,但又有继承层次,可以通过基类(exception)
引用或指针来使用。这种设计在应用程序里最好避免,因为很容易引起
object-slicing:

exception e = domain_error( "sqrt(NegativeNumber)" );

上面一行能编译,能运行,但没有做想让它做的事。


“概念实现”:(象“值”一样简单,但不是用来装一个“值”的)

iterator<>, input_iterator_tag, output_iterator_tag...,
unary_function<>, binary_function<>...。


“特征描述”

iterator_traits<>, char_traits<>, numeric_limits<>...。


“怪物”:

auto_ptr<>。

分享到:
评论

相关推荐

    大华无插件播放项目111

    大华无插件播放项目111

    Oracle 19c 数据库备份恢复与导入导出实战指南

    内容概要:本文详细介绍了Oracle 19c数据库的备份恢复和导入导出操作。首先概述了基本命令,然后分别讲述了三种工作方式(交互式、命令行、参数文件)和三种模式(表、用户、全库)。接着介绍了高级选项,如分割成多个文件、增量导出/导入、以SYSDBA进行导出/导入、表空间传输等。最后讨论了优化技巧,包括加快导出和导入速度的方法。还解决了一些常见问题,如字符集问题和版本问题。 适用人群:Oracle数据库管理员和相关技术人员。 使用场景及目标:适合在日常数据库管理和维护中进行数据备份、恢复、导入和导出操作,提高数据安全性和管理效率。 其他说明:文章内容丰富,涉及多种实用技巧,适用于不同场景下的具体操作,有助于提升工作效率。

    大数据旅游酒店大数据可视化项目

    基于Python Flask开发的旅游酒店大数据可视化项目,可以直接运行。 操作步骤: 1. 解压缩项目文件 2. 使用 pycharm打开项目 3. 运行项目中的app.py文件 注意:需要确保项目的Flask Python相关的环境已经搭建完成。

    模拟立体翻转效果,非Gallery实现.zip

    Android 毕业设计,Android 毕业设计,小Android 程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    仿360 浮动小插件效果.zip

    Android 毕业设计,Android 毕业设计,小Android 程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告

    基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告,个人高分设计项目、经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的学生和需要项目实战练习的学习者。 基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告基于stm32和openmv的电赛校赛自动泊车题目源码+文档设计报告个人高分设计项目、经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的学生和需要项目实战练习的学习者。 个人高分设计项目、经导师指导并认可通过的高分设

    棉花检测20-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar

    棉花检测20-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar棉-V2释放 ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 它包括406张图像。 以可可格式注释棉花。 将以下预处理应用于每个图像: 没有应用图像增强技术。

    javaweb社区医院挂号系统-lw.zip

    项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧!

    python-3.11.11-amd64.exe

    windwos环境下python 3.11系列64位安装包,仅推荐个人学习、开发、娱乐或者测试环境下使用。

    基于ssm的精品酒销售管理系统+jsp源代码(完整前后端+mysql+说明文档+LW).zip

    使用精品酒销售管理系统的用户分管理员和用户两个角色的权限子模块。 管理员所能使用的功能主要有:主页、个人中心、用户管理、商品分类管理、商品信息管理、系统管理、订单管理等。 用户可以实现主页、个人中心、我的收藏管理、订单管理等。 前台首页可以实现商品信息、新闻资讯、我的、跳转到后台、购物车等。 项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    Video_2024-12-18_000023.wmv

    Video_2024-12-18_000023.wmv

    ppt最終版asasaadd

    ppt最終版asasaadd

    计算机图形学试卷第一套

    计算机图形学期末考试

    springboot-基于SpringBootVue的家具商城系统设计与实现.zip

    springboot-基于SpringBootVue的家具商城系统设计与实现.zip

    PenTablet_5.2.4-5.zip

    PenTablet_5.2.4-5.zip

    基于ssm的企业人力资源管理系统源代码(完整前后端+mysql+说明文档+LW).zip

    考虑了企业管理者的实际工作环境和需求,最终将人力资源系统划分为5个部分,即登录模块、组织发展模块、员工团队模块、合同管理模块、党建管理模块。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    QT5.12.9音乐播放器MP3 免费下载交流学习

    QT音乐播放器MP3 可点击播放可上一首下一首可调节音量 可暂停可上传音乐

    椅子检测6-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar

    椅子检测6-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar对象检测实验室-V1 2023-08-21 2:28 PM ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解和搜索非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 对于最先进的计算机视觉培训笔记本,您可以与此数据集一起使用 该数据集包括997张图像。 对象以可可格式注释。 将以下预处理应用于每个图像: *像素数据的自动取向(带有Exif-Arientation剥离) *调整大小为640x640(拉伸) 应用以下扩展来创建每个源图像的3个版本: *将盐和胡椒噪声应用于10%的像素

    Python项目-实例-13 截图工具.zip

    Python课程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    Altas PF拧紧枪 OP协议,开发协议

    Altas PF拧紧枪 OP协议,开发协议

Global site tag (gtag.js) - Google Analytics