国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

[開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝

這篇具有很好參考價值的文章主要介紹了[開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

寫在前面:Python和C++中的賦值與深淺拷貝,由于其各自語言特性的問題,在概念和實現(xiàn)上稍微有點差異,本文將這C++和Python中的拷貝與賦值放到一起,希望通過對比學(xué)習(xí)兩語言實現(xiàn)上的異同點,加深對概念的理解。

1. Python中的賦值、淺拷貝、深拷貝

C++中所謂的 淺拷貝就是由(系統(tǒng)默認的)拷貝構(gòu)造函數(shù)對數(shù)據(jù)成員進行逐一的賦值 ,通常默認的拷貝構(gòu)造函數(shù)就是可以達到該效果的,但是如果類中有指針類型的數(shù)據(jù)(需要在堆上分配內(nèi)存),那么此時使用默認的拷貝構(gòu)造函數(shù)就會帶來錯誤。因為此時采用簡單的淺拷貝,則兩個類中的兩個指針將指向同一個地址,當(dāng)對象釋放時,會調(diào)用兩次析構(gòu)函數(shù),而導(dǎo)致指針懸掛現(xiàn)象(懸浮指針)。

而C++的 深拷貝則是,使用自定義的拷貝構(gòu)造函數(shù),將原有對象的所有成員變量拷貝給新對象,對于指針等數(shù)據(jù)還會為新對象重新在堆上分配一塊內(nèi)存,并將原有對象所持有的堆上的數(shù)據(jù)也拷貝過來,這樣能保證原有對象和新對象所持有的動態(tài)內(nèi)存都是相互獨立的,更改一個對象的數(shù)據(jù)不會影響另一個對象,同時也不會造成double free的錯誤。

C++中的 賦值,默認調(diào)用的是默認的拷貝構(gòu)造函數(shù)即淺拷貝,如果要使用深拷貝需要重載賦值運算符,為動態(tài)內(nèi)存在堆上分配空間即可~

C++ 淺拷貝示例:

  #include <iostream>

  // 淺拷貝 使用默認的構(gòu)造函數(shù)
  class shallowCopy {
  public:
      shallowCopy(int len) : m_len(len) {
          m_ptr = new int(0); // m_ptr指向一個值為0的int
      }
      shallowCopy() {}

      ~shallowCopy() {
          delete m_ptr;
      }

  public: // 定義為public,方便輸出
      int* m_ptr;
      int m_len;
  };

int main()
{
  shallowCopy sc(1);
  auto sc1 = sc; // 淺拷貝
  std::cout << "shallowCopy: " << std::endl;
  std::cout << "sc.m_ptr = " << sc.m_ptr << std::endl;
  std::cout << "sc1.m_ptr = " << sc1.m_ptr << std::endl;  
}

>>>shallowCopy: 
sc.m_ptr = 0x560c930aeeb0
sc1.m_ptr = 0x560c930aeeb0
free(): double free detected in tcache 2  // 嘗試兩次釋放同一地址?。?!報錯
Aborted

C++ 深拷貝示例:

#include <iostream>

  
class deepCopy {
  public:
      deepCopy(int len) : m_len(len) {
          std::cout << "call deepCopy(int len) " << std::endl;
          m_ptr = new int(1);
      }
      deepCopy(const deepCopy& deepcopy) {
          std::cout << "call deepCopy(const deepCopy& deepcopy) " << std::endl;
          m_len = deepcopy.m_len;
          m_ptr = new int(*(deepcopy.m_ptr)); // 重新分配內(nèi)存,并且賦值
      } // 拷貝構(gòu)造函數(shù)
      ~deepCopy() {
          delete m_ptr;
      }

  public:
      int* m_ptr;
      int m_len;
 };

int main()
{	
  std::cout << "deepCopy: " << std::endl;
  deepCopy dc(1);
  deepCopy dc1(dc); // 深拷貝
  std::cout << "dc.m_ptr = " << dc.m_ptr << std::endl;
  std::cout << "dc1.m_ptr = " << dc1.m_ptr << std::endl;    
}

>>>deepCopy: 
call deepCopy(int len) 
call deepCopy(const deepCopy& deepcopy) 
dc.m_ptr = 0x560c930af2e0
dc1.m_ptr = 0x560c930af300

2. C++中的賦值、淺拷貝、深拷貝

在Python參數(shù)傳遞,“值傳遞”還是“引用傳遞“?一文中我們從Python中可變對象與不可變對象的角度理解了Python中的參數(shù)傳遞的方式,在賦值、深拷貝、淺拷貝中,我們同樣從這個角度入手,理解Python中的深淺拷貝。對可變對象、不可變對象不是很清晰的同學(xué),可以移步鏈接復(fù)習(xí)一下~。

  • 不可變對象:一旦創(chuàng)建就不可修改的對象,包括字符串、元組、數(shù)值類型

(該對象所指向的內(nèi)存中的值不能被改變。當(dāng)改變某個變量時候,由于其所指的值不能被改變,相當(dāng)于把原來的值復(fù)制一份后再改變,這會開辟一個新的地址,變量再指向這個新的地址。)

  • 可變對象:可以修改的對象,包括列表、字典、集合

(該對象所指向的內(nèi)存中的值可以被改變。變量(準確的說是引用)改變后,實際上是其所指的值直接發(fā)生改變,并沒有發(fā)生復(fù)制行為,也沒有開辟新的地址,通俗點說就是原地改變。)


2.1 概念

  1. 賦值,類似于C++中的引用(別名),只是復(fù)制了新對象的引用,不會開辟新的內(nèi)存空間,Python中賦值的一般形式為a = 'nihao',內(nèi)存中實現(xiàn)是:內(nèi)存開辟空間存儲字符串nihao,將a指向這塊內(nèi)存空間:

[開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝,開發(fā)語言之C++ &amp; Python,c++,開發(fā)語言

  1. 淺拷貝: 創(chuàng)建新對象,其內(nèi)容是原對象的引用。

? Python中的淺拷貝有三種形式: 切片操作,工廠函數(shù),copy模塊中的copy函數(shù)。

? 如: lst = [1,2,[3,4]]

? 切片操作lst1 = lst[:] 或者 lst1 = [each for each in lst]

? 工廠函數(shù):lst1 = list(lst)

? copy函數(shù):lst1 = copy.copy(lst)

?

? 淺拷貝之所以稱為淺拷貝,是因為它僅僅只拷貝了一層,拷貝了最外圍的對象本身,內(nèi)部的元素都只是拷貝了一個引用而已,如在lst中有一個嵌套的 list[3,4],如果我們修改了它,情況就不一樣了。

? 淺拷貝要分兩種情況進行討論:

? 1)當(dāng)淺拷貝的值是 不可變對象(字符串、元組、數(shù)值類型) 時和“賦值”的情況一樣,對象的id值 (id()函數(shù)用于獲取對象的內(nèi)存地址) 與淺拷貝原來的id值相同。

? 2)當(dāng)淺拷貝的值是 可變對象(列表、字典、集合) 時會產(chǎn)生一個“不是那么獨立的對象”存在。

? 2.1) 拷貝的可變對象中無復(fù)雜子對象,原來值的改變并不會影響淺拷貝的值,同時淺拷貝的值改變也并不會影響原來的值。

? 2.2) 拷貝的可變對象中有復(fù)雜子對象(例如列表中的一個子元素是一個列表),如果不改變其中復(fù)雜子對象,淺拷貝的值改變并不會影響原來的值。 但是改變原來的值中的復(fù)雜子對象的值會影響淺拷貝的值。

  1. 深拷貝:和淺拷貝對應(yīng),深拷貝拷貝了對象的所有元素,包括多層嵌套的元素。深拷貝出來的對象是一個全新的對象,不再與原來的對象有任何關(guān)聯(lián)。

只有一種形式,copy模塊中的deepcopy函數(shù)

2.2 示例:從例子中理解

1) 不可變對象的賦值、深拷貝、淺拷貝
import copy

# 不可變對象,無法添加刪除元素
a = (1, 2, 3)

print("==========")
b = a
print(a, b)
print(id(a), id(b))

print("=====shallow copy=====")
s = copy.copy(a)
print(a, s)
print(id(a), id(s))

print("=====deep copy=====")
d = copy.deepcopy(a)
print(a, d)
print(id(a), id(d))

>>>==========
((1, 2, 3), (1, 2, 3))
(4564433008, 4564433008)
=====shallow copy=====
((1, 2, 3), (1, 2, 3))
(4564433008, 4564433008)
=====deep copy=====
((1, 2, 3), (1, 2, 3))
(4564433008, 4564433008)
2) 可變對象的賦值、淺拷貝與深拷貝
import copy

a = [1, 2, 3]
print("==========")
b = a
b.append(4)
print(a, b)
print(id(a), id(b)) # 賦值僅是變量的別名,兩變量擁有相同的內(nèi)存地址,無論更改哪一個另一個都會更改

a = [1, 2, 3]
print("=====shallow copy=====")
s = copy.copy(a)
print(a, s)
print(id(a), id(s))
a.append(4)
print("------append 4-------")
print(a, s)
print(id(a), id(s))

a = [1, 2, 3]
print("=====deep copy=====")
d = copy.deepcopy(a)
print(a, d)
print(id(a), id(d))
print("------append 4-------")
a.append(4)
print(a, d)
print(id(a), id(d))


>>>==========
([1, 2, 3, 4], [1, 2, 3, 4])
(4564157144, 4564157144)
=====shallow copy=====
([1, 2, 3], [1, 2, 3])
(4564158440, 4564158512)
------append 4-------
([1, 2, 3, 4], [1, 2, 3])
(4564158440, 4564158512)
=====deep copy=====
([1, 2, 3], [1, 2, 3])
(4564158368, 4564158440)
------append 4-------
([1, 2, 3, 4], [1, 2, 3])
(4564158368, 4564158440)
3) 可變對象深淺拷貝(外層、內(nèi)層改變元素)

[開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝,開發(fā)語言之C++ &amp; Python,c++,開發(fā)語言

# 外層元素更改
import copy
l = [1, 2, 3, [4, 5]]

l1 = l
l2 = copy.copy(l)
l3 = copy.deepcopy(l)
l.append(6) 

print(l)
print(l1)
print(l2)
print(l3)

>>>[1, 2, 3, [4, 5], 6]
[1, 2, 3, [4, 5], 6]
[1, 2, 3, [4, 5]]
[1, 2, 3, [4, 5]]

# 內(nèi)層元素更改
import copy
l = [1,2,3,[4, 5]]

l1 = l #賦值
l2 = copy.copy(l) #淺拷貝
l3 = copy.deepcopy(l) #深拷貝
l[3].append(6) 

print(l) 
print(l1)
print(l2)
print(l3)

>>> [1, 2, 3, [4, 5, 6]] 
[1, 2, 3, [4, 5, 6]] 
[1, 2, 3, [4, 5, 6]] 
[1, 2, 3, [4, 5]]
  1. 外層添加元素時,淺拷貝不會隨原列表變化而變化;內(nèi)層添加元素時,淺拷貝才會變化。

  2. 無論原列表如何變化,深拷貝都保持不變。

  3. 賦值對象隨著原列表一起變化。文章來源地址http://www.zghlxwxcb.cn/news/detail-785412.html

到了這里,關(guān)于[開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Java中的淺拷貝與深拷貝

    在Java中,對象的拷貝有兩種方式:淺拷貝和深拷貝。它們分別代表了不同的拷貝方式,拷貝出的新對象與原始對象之間存在一定的差異。本文將詳細介紹淺拷貝和深拷貝的概念、特點和實現(xiàn)方式,并且通過實例進行解析。 ?一、淺拷貝 ?淺拷貝是指在對一個對象進行拷貝時,

    2024年02月14日
    瀏覽(30)
  • C#中的淺拷貝與深拷貝

    C#中的淺拷貝與深拷貝

    眾所周知,C#中有兩種類型變量:那就是 值類型 和 引用類型 。對于值類型而言,copy就相當(dāng)于是全盤復(fù)制了,真正的實現(xiàn)了復(fù)制,屬于 深拷貝 ;而對于引用類型而言,一般的copy只是 淺拷貝 ,只是copy到了引用對象的地址,相當(dāng)于值傳遞了一個引用指針, 新的對象通過地址

    2024年02月11日
    瀏覽(20)
  • 詳解js中的淺拷貝與深拷貝

    詳解js中的淺拷貝與深拷貝

    1.1 棧(stack)和堆(heap) 棧(stack):由操作系統(tǒng)自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧; 堆(heap):一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時可能由OS回收,分配方式倒是類似于鏈表 1.2 基本數(shù)據(jù)類型和引用數(shù)據(jù)類

    2024年02月08日
    瀏覽(19)
  • Pandas數(shù)據(jù)中的淺拷貝與深拷貝

    Pandas數(shù)據(jù)中的淺拷貝與深拷貝

    pandas庫主要有兩種數(shù)據(jù)結(jié)構(gòu)DataFrames和Series。這些數(shù)據(jù)結(jié)構(gòu)在內(nèi)部用索引數(shù)組和數(shù)據(jù)數(shù)組表示,索引數(shù)組標記數(shù)據(jù),數(shù)據(jù)數(shù)組包含實際數(shù)據(jù)?,F(xiàn)在,當(dāng)我們試圖復(fù)制這些數(shù)據(jù)結(jié)構(gòu)(DataFrames和Series)時,我們實際上是復(fù)制對象的索引和數(shù)據(jù),有兩種方法可以做到這一點,即淺復(fù)

    2024年02月09日
    瀏覽(17)
  • [開發(fā)語言][python][c++]:C++中的this指針和Python中的Self -- 26歲生日

    以朋友的新歲祝福開篇,祝筆者也祝大家??: 之前一直對 C++ 中的 this 和 python 中的 self 到底是什么關(guān)系,為什么 C++ 要顯式的寫出來,python 則不需要? 模糊不清,趁著周末整理一下相關(guān)結(jié)論,希望本篇文章可以解答這些問題,同時對C++和Python中的類加深些理解。 python 當(dāng)

    2024年01月24日
    瀏覽(31)
  • 詳解python列表等對象的賦值和復(fù)制(淺拷貝copy()及深拷貝deepcopy()的使用區(qū)別與示例)

    python雖然沒有指針的概念,但是對象、引用、地址這些內(nèi)容還是存在的,尤其是像列表對象、某類型對象的引用上,搞清楚對象變量的復(fù)制和賦值很有必要,不然容易出現(xiàn)“莫名其妙”的錯誤。 python中給一個變量 a 賦值列表實際上是創(chuàng)建了一個列表對象,并將該列表的地址賦

    2024年02月04日
    瀏覽(22)
  • C++的引用 拷貝賦值和引用賦值

    C++的引用 拷貝賦值和引用賦值

    ? ? ?? 博客內(nèi)容:C++的引用 拷貝賦值和引用賦值 ?? 作??者:陳大大陳 ?? 個人簡介:一個正在努力學(xué)技術(shù)的準前端,專注基礎(chǔ)和實戰(zhàn)分享 ,歡迎私信! ?? 歡迎大家:這里是CSDN,我總結(jié)知識和寫筆記的地方,喜歡的話請三連,有問題請私信 ?? ?? ?? 目錄 引用? 引用

    2024年02月12日
    瀏覽(29)
  • c++拷貝構(gòu)造與賦值運算符重載

    c++拷貝構(gòu)造與賦值運算符重載

    目錄 目錄: ? ? ? ? 1:拷貝構(gòu)造 ? ? ? ? 2:賦值運算符重載 ???????? ? ? ? ? 前言:在上一章我們已經(jīng)學(xué)習(xí)過了,構(gòu)造與析構(gòu)這兩個默認成員函數(shù)了,接下來讓我們一起來學(xué)習(xí)另外兩個重要的默認成員函數(shù)。 ? ? ? ? 首先讓我們來講一下默認成員函數(shù)這個概念,所謂

    2024年02月08日
    瀏覽(25)
  • 【C++】vector類的模擬實現(xiàn)(增刪查改,拷貝構(gòu)造,賦值運算,深淺拷貝)

    【C++】vector類的模擬實現(xiàn)(增刪查改,拷貝構(gòu)造,賦值運算,深淺拷貝)

    ??博客主頁: 主頁 ??系列專欄: C++ ??感謝大家點贊??收藏?評論?? ??期待與大家一起進步! 我們模擬vector是用迭代器(start,end,endofstorage)來控制增刪查改操作的 1普通構(gòu)造 2迭代器構(gòu)造 3初始化字符構(gòu)造 4拷貝構(gòu)造: 1當(dāng)前大小(size()) 2總體容量(capacity()) 1begin()

    2024年02月15日
    瀏覽(19)
  • C++拷貝構(gòu)造函數(shù)與賦值運算符重載

    C++拷貝構(gòu)造函數(shù)與賦值運算符重載

    顧得泉: 個人主頁 個人專欄: 《Linux操作系統(tǒng)》?《C++從入門到精通》??《LeedCode刷題》 鍵盤敲爛,年薪百萬! ???????在現(xiàn)實生活中,可能存在一個與你一樣的自己,我們稱其為雙胞胎。 ???????那在創(chuàng)建對象時,可否創(chuàng)建一個與已存在對象一某一樣的新對象呢? ?

    2024年02月22日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包