C++物件語義與值語義
一、值語義
-
所謂值語義是一個物件被系統標準的複製方式複製後,與被複制的物件之間毫無關係,可以彼此獨立改變互不影響
實現
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 = newArrayList<Integer>(); List<Integer> second = first; second.add(1000); System.out.println(first.size()); //1 System.out.println(second.size());//1 |
注:
-
即使在具有垃圾回收的系統中,資源釋放依然是個問題,因為資源不止記憶體,還有網路埠,資料庫連結等
-
錄一篇 wangtianxing 老師的觀點,比我說的清楚有趣的多:
我認為“值”與“物件”的區分在設計和實現時具有非常重要的指導作用, |
---|
轉載於: http://blog.csdn.net/chelsea/article/details/439332
相關推薦
C++物件語義與值語義
一、值語義 所謂值語義是一個物件被系統標準的複製方式複製後,與被複制的物件之間毫無關係,可以彼此獨立改變互不影響 實現 C++ Java 標準複製方式 賦值、拷貝構造 賦值,clone() 基本資料型別 包括整數,浮點數,布林值,字元,指標等,全部為值語義 包括整數,浮點
C語言缺陷與陷阱語義分析
語義分析 (程式設計師本意是希望表示某種事物,而實際表示的卻是另外一種事物) 1. 指標和陣列 陣列值必須注意的兩點:(1)C語言只有一維陣列,且陣列大小必須在編譯期作為一個常數確定下來;(2)對一個數組只能進行:確定該陣列的大小,以及獲得指向該陣列下標為0
C 物件 檔案與二進位制串(byte陣列)之間的轉換
1.關於本文在使用C#下的TCP(類TcpClient)、UDP(類UdpClient)協議傳輸資訊時,都需要將資訊轉換為byte型別的陣列進行傳送。本文實現了兩種object與byte陣列的轉換和一種檔案與byte陣列轉換的方式。基礎型別的資料,可以用BitConv
C++物件屬性與初始化規則
推薦使用初始化列表初始化 初始化列表我們不寫,但是編譯器依然會自動初始化一次 ———》針對自定義型別 宣告和定義,宣告是告訴程式我要定義這個東西 定義是實際開闢空間,分配記憶體 初始化列表可以認為初始化列表是成員變數定義的地方。 必須放在初始化列表:
C++物件到bool值的轉換
問題 最近在使用pugixml,在閱讀原始碼自帶的例程時(docs/samples/load_error_handling.cpp),發現有段程式碼比較迷惑, 這裡生成了一個xml_parse_result的物件result,用於接受doc.load_s
C++之值語義與物件語義
●iostream擴充套件 #include <ostream> // 是不是太重量級了? class Date { public: Date(int year, int month, int day) : year_(year), month_
C++11 標準新特性: 右值引用與轉移語義
https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ 特性的目的 右值引用 (Rvalue Referene) 是 C++ 新標準 (C++11, 11 代表 2011 年 ) 中引入的新特性
C++11移動語義探討——從臨時物件到右值引用
一.前言 這篇文章主要談談c++11中引入的右值引用概念和移動語義概念。以及這些東西可能在我們程式設計中帶來哪些體驗、便捷或者是程式碼效率的提高。 文章主要分為以下三點: 臨時物件的產生 何謂右值引用 何謂移動語義 二.臨時物件的產生 在我們以
c++ 特性: 右值引用與移動語義
c++11中引入了右值引用。 左值與右值 先區分左值與右值,這裡參考c++ 右值引用中對左值和右值區分方法: 左值和右值都是針對表示式,左值是指表示式結束後依然存在的持久物件,右值是指表示式結束時就不再存在的臨時物件。 一個區分左值和右值的簡便方法是
[C++] 右值引用:移動語義與完美轉發
C++11 引入的新特性中,除了併發記憶體模型和相關設施,這些高帥富之外,最引人入勝且接地氣的特性就要屬『右值引用』了(rvalue reference)。加入右值引用的動機在於效率:減少不必要的資源拷貝。考慮下面的程式: std::vector<string>
C++11執行緒指南(4)--右值引用與移動語義
1. 按值傳遞 什麼是按值傳遞? 當一個函式通過值的方式獲取它的引數時,就會包含一個拷貝的動作。編譯器知道如何去進行拷貝。如果引數是自定義型別,則我們還需要提供拷貝建構函式,或者賦值運算子來進行深拷貝。然而,拷貝是需要代價的。在我們使用STL容器時,就存在大量的拷貝
對C++11中的`移動語義`與`右值引用`的介紹與討論
本文主要介紹了C++11中的移動語義與右值引用, 並且對其中的一些坑做了深入的討論. 在正式介紹這部分內容之前, 我們先介紹一下rule of three/five原則, 與copy-and-swap idiom最佳實踐. 本文參考了stackoverflow上的一些回答. 不能算是完全原創 rule
[技術]淺談初始化語義與賦值語義
真的 class 基本 復制構造函數 spa 數值 復制構造 得到 對數 背景 博主是一個常年使用初始化語義的coder= =,所以經常會遇到這樣的對話 int tmp(0); XXX:誒,你這tmp函數是幹什麽的啊 博主:蛤?我哪裏定義了tmp函數了
深度探索C++物件模型——物件(5)——程式轉化語義
我們寫的程式碼,編譯器會對程式碼進行拆分,拆分成編譯器更容易理解和實現的程式碼,接下來將從我們程式設計師寫程式碼角度和編譯器理解角度去分析一些情況 1.定義時初始化物件 (1)程式設計師角度 #include <iostream> using namespace std;
深度探索C++物件模型(4)——物件(4)——拷貝建構函式語義
傳統認識認為:如果我們沒有定義一個自己的拷貝建構函式,編譯器會幫助我們合成 一個拷貝建構函式。 結論:這個合成的拷貝建構函式,也是在 必要的時候才會被編譯器合成出來。 示例程式碼 class A { public
深度探索C++物件模型(3)——物件(3)——建構函式語義
預設建構函式(預設建構函式)分析 即沒有引數的建構函式 傳統認識認為:如果我們自己沒定義任何建構函式,那麼編譯器就會為我們隱式自動定義 一個預設的建構函式, 我們稱這種建構函式為:“合成的預設建構函式” &n
C++第三章(類和物件)下篇 (動態建立與釋放,物件的賦值和複製,靜態資料成員,友元)
一,物件的動態建立與釋放 new (程式設計師怎麼會沒有朋友??? 來讓我給你new 一個) 在我學過的c中 我們一般都用 malloc 來動態申請空間。現在我們可以用new 來申請空間 Box *pt; pt = new Box; c++允許在new時進行賦值 Box *
右值引用與move語義
右值 C語言中,左值(left value, lvalue)只出現在賦值符左邊的量,右值(right value, rvalue)是出現在賦值符右邊的量。在C++中,右值的定義稍微不同,每一個表示式都會產生一個左值或者右值,所以表示式也稱左值表示式或右值表示式
C++物件賦值與C#物件賦值----C++與C#值傳遞與引用傳遞淺析
在C#中,看下面一段程式: class A { public int value; public A(int x) { value = x; } public
C++11特性--右值引用,移動語義,強制移動move()
1.右值引用 *右值:不能對其應用地址運算子的值。 *將右值關聯到右值引用導致該右值被儲存到特定的位置,且可以獲取該位置的地址 *右值包括字面常量(C風格字串除外,它表示地址),諸如X+Y等表示式以及返回值得函式(條件是該函式返回的不是引用) *引入右值引用的主要目的之一是實行移動語義 E