Clone函數

概述

Clone函數是一種用于復制的計算機函數。在程序編寫中,除了自定義一個拷貝構造函數來實現對象復制外,還可以實現一個clone函數。這需要借助編譯器實現的一個隱藏拷貝構造函數,這樣的做法,更省心。

中文名clone函數
外文名clone
所屬學科信息學

基本介紹

在C++中,要拷貝一個對象,除了自定義一個拷貝構造函數來實現對象復制外,還可以實現一個clone函數。這需要借助編譯器實現的一個隱藏拷貝構造函數,這樣的做法,更省心。

背后的原理是C++的原型(Prototype)模式:用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。

Prototype模式提供了一個通過已存在對象進行新對象創建的接口(Clone), Clone實現和具體的語言相關,在C++中通過拷貝構造函數實現。

注意:clone函數是virtual的,無法內聯。

示例代碼:

?

#include "stdafx.h"
#include <iostream>class CA
{
public:int value;CA* clone() const { return new CA( *this );}//僅一個構造函數CA(int a ){value=a;}   
};int _tmain(int argc, _TCHAR* argv[])
{CA* objA=new CA(10);CA* objtemp=objA->clone();delete objA;std::cout<<objtemp->value;delete objtemp;return 0;
}

Prototype 模式的應用場景在于,你拿到一個 Base* ,它指向某個 Derived 對象,你想克隆出 Derived 對象,但代碼中不寫出 Derived 的具體類型,因為有很多派生類,這種情況下你用構造函數是搞不定的,就需要Prototype 模式了。

原型模式的作用

1、基本就是你需要從A的實例得到一份與A內容相同,但是又互不干擾的實例的話,就需要使用原型模式。

2、用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。這個其實和C++的拷貝構造函數的作用是相似的(但不相同),實際上就是動態抽取 當前對象運行時的狀態

Clone方法

關于clone方法

在說明clone方法之前,需要對值傳遞和引用傳遞有個初步的了解

其中需要注意的是第三條

(1)基本數據類型傳值,對形參的修改不會影響實參;

(2)引用類型傳引用,形參和實參指向同一個內存地址(同一個對象),所以對參數的修改會影響到實際的對象;

(3)String, Integer, Double等immutable的類型特殊處理,可以理解為傳值,最后的操作不會修改實參對象。(其本質上還是引用傳遞,只不過這些類型是不可變類,可以理解為傳值)

在對值傳遞和引用傳遞有個初步了解之后,我們開始講解clone方法。

使用clone方法的步驟

1、實現clone的類首先需要繼承Cloneable接口以,此接口是一個標識接口,沒有任何接口方法

2、在類中重寫Object類的clone方法

3、在clone方法中調用super.clone

這樣就可以得到實現clone類的的一個Object對象的復制,但這存在一個問題,如果這個類中還存在引用類型怎么辦?在就要對淺復制和深復制說明一下了。

淺復制和深復制

1、類中的成員皆為基本數據類型,使用淺復制

2、類中的成員有引用類型(此時需注意String, Integer, Double等immutable的類型特殊看待,不當成引用類型),使用深復制

淺復制和深復制的使用依據實際情況而定

淺復制:被復制對象的所有變量都含有與原來對象相同的值,引用變量仍然指向原來的對象

深復制:被復制對象的所有變量都含有與原來對象相同的值引用,引用變量指向被復制對象的新變量

原型模式的優勢

一.為什么不用new直接新建對象,而要用原型模式?

首先,用new新建對象不能獲取當前對象運行時的狀態,其次就算new了新對象,在將當前對象的值復制給新對象,效率也不如原型模式高。

二.為什么不直接使用拷貝構造函數,而要使用原型模式?

原型模式與拷貝構造函數是不同的概念,拷貝構造函數涉及的類是已知的,原型模式涉及的類可以是未知的。

原型模式生成的新對象可能是一個派生類。拷貝構造函數生成的新對象只能是類本身。原型模式是描述了一個通用方法(或概念),它不管是如何實現的,而拷貝構造則是描述了一個具體實現方法。

    class base  {  public :   base();  base(base &obj);  virtual  ~base();  virtual base *clone() { return new base(*this) ; };  };  class derived : public base  {  public :   derived();  derived(  derived &);  virtual base *clone(){return new derived (*this); }  ....  };  base *obj1 = new base ;   base *obj2 = new derived ;//基類指針指向派生類對象,怎樣用基類指針創建一個新的派生類對象?? 用基類的拷貝構造函數顯然不行。  base *obj3 = obj1 .clone();  base *obj4 = obj12.clone();  

適用場景

1.資源優化場景

類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。

2.性能和安全要求的場景

通過new產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。

3.一個對象多個修改者的場景

一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。

缺點

1、配備克隆方法需要對類的功能進行通盤考慮,這對于全新的類不是很難,但對于已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。

2、實現原型模式每個派生類都必須實現 Clone接口。

3、逃避構造函數的約束。


參考資料

  • 1??C++ clone()函數的用法???.CSDN
  • 2?【Linux內核】Clone函數和Cloneable接口簡要說明?
  • 3??IT職場筆記???.博客園
  • 4??關于clone()方法???.CSDN
  • 5?Pytorch中clone(),copy_(),detach(),.data的辨析與應用??知乎
  • 6?java中的clone_51CTO博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36100.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36100.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 使用FFmpeg.Autogen對byte[]進行編解碼

C# 使用FFmpeg.Autogen對byte[]進行編解碼&#xff0c;參考&#xff1a;https://github.com/vanjoge/CSharpVideoDemo 入口調用類&#xff1a; using System; using System.IO; using System.Drawing; using System.Runtime.InteropServices; using FFmpeg.AutoGen;namespace F…

C++11異步與通信之 packaged_task

概念簡介 packaged_task 用于包裝可調用目標(Callable)為一個對象,如lambda&#xff0c;普通函數&#xff0c;小括號重載等&#xff0c;用于異步調用。 其返回值或所拋異常被存儲于能通過 std::future 對象訪問的共享狀態中&#xff0c;和promise類似。 將函數的調用與函數返…

時序預測 | MATLAB實現EEMD-LSTM、LSTM集合經驗模態分解結合長短期記憶神經網絡時間序列預測對比

時序預測 | MATLAB實現EEMD-LSTM、LSTM集合經驗模態分解結合長短期記憶神經網絡時間序列預測對比 目錄 時序預測 | MATLAB實現EEMD-LSTM、LSTM集合經驗模態分解結合長短期記憶神經網絡時間序列預測對比效果一覽基本介紹模型搭建程序設計參考資料 效果一覽 基本介紹 時序預測 | …

小龜帶你妙寫排序之快速排序

快速排序 一. 快速排序原理二. 題目三. 快速排序的思路分析&#xff08;圖文結合&#xff09;四.代碼 一. 快速排序原理 先從數據序列中選一個元素&#xff0c;并將序列中所有比該元素小的元素都放到它的右邊或左邊&#xff0c;再對左右兩邊分別用同樣的方法處之直到每一個待處…

runtime error: member access within misaligned address(力扣最常見錯誤之一)

runtime error: member access within misaligned address&#xff08;力扣最常見錯誤之一&#xff09; 前言原因和解決辦法總結 前言 最近博主在刷力扣時&#xff0c;明明代碼邏輯都沒問題&#xff0c;但總是報下面這個錯誤&#xff1a; runtime error: member access within…

django實現登錄和登錄的鑒權

1、創建數據庫的管理員表 在models.py 中定義admin表&#xff0c;為了簡單&#xff0c;表里只有用戶名和密碼還有默認加的id 三個字段 from django.db import models# Create your models here.class Admin(models.Model):username models.CharField(verbose_name"用戶…

源碼框架-三勾軟件

javaspringboot微信小程序商城SAAS前后端源碼: 三勾商城是開發友好的微信小程序商城&#xff0c;框架支持SAAS&#xff0c;支持發布 iOS Android 公眾號 H5 各種小程序&#xff08;微信/支付寶/百度/頭條/QQ/釘釘/淘寶&#xff09;等多個平臺&#xff0c;不可多得的二開神器…

訓練用于序列分類任務的 RoBERTa 模型的適配器

介紹 NLP當前的趨勢包括下載和微調具有數百萬甚至數十億參數的預訓練模型。然而,存儲和共享如此大的訓練模型非常耗時、緩慢且昂貴。這些限制阻礙了 RoBERTa 模型開發更多用途和適應性更強的 NLP 技術,該模型可以從多個任務中學習并針對多個任務進行學習;在本文中,我們將重…

Kafka:安裝和配置

producer&#xff1a;發布消息的對象&#xff0c;稱為消息產生者 &#xff08;Kafka topic producer&#xff09; topic&#xff1a;Kafka將消息分門別類&#xff0c;每一個消息稱為一個主題&#xff08;topic&#xff09; consumer&#xff1a;訂閱消息并處理發布消息的對象…

模擬 枚舉

分享牛客算法基礎精選題單題目打卡!!! 目錄 字符串的展開 多項式輸出 機器翻譯 : 鋪地毯 : [NOIP2016]回文日期 字符串的展開 原題鏈接 : 字符串的展開 思路 : 模擬 代碼 : #include<iostream> #include<cstring> #include<algorithm> using na…

Java課題筆記~ ServletContext

單個Servlet的配置對象 web.xml <servlet><servlet-name>FirstServlet</servlet-name><servlet-class>com.ambow.test.FirstServlet</servlet-class><init-param><param-name>charset</param-name><param-value>utf-8&…

centos自動同步北京時間

1、安裝ntpdate服務 yum -y install ntpdate 2、加入自動任務計劃 查找ntpdate的路徑&#xff1a; which ntpdate 復制這個路徑。 編輯自動任務計劃并加入ntpdate&#xff1a; crontab -e # 每小時第30分鐘同步AD域控時間 30 * * * * /usr/sbin/ntpdate -u 192.168.2.8 > …

DP——動態規劃

DP——動態規劃 動態規劃算法動態規劃的一般步驟特殊DP——背包0-1背包問題完全背包問題 總結 動態規劃算法 當涉及到解決具有重疊子問題的優化問題時&#xff0c;動態規劃是一種常用的算法技術。它通過將問題分解為一系列重疊子問題&#xff0c;并使用遞歸或迭代的方式來解決…

Spring Cloud Gateway系例—GatewayFilter 工廠

目錄 6.1.AddRequestHeader 6.2.AddRequestHeadersIfNotPresent 6.3.AddRequestParameter 6.4.AddResponseHeader 6.5.CircuitBreaker 6.5.1. 熔斷指定的狀態碼 6.6.CacheRequestBody 6.7.DedupeResponseHeader 6.8.FallbackHeaders 6.9.JsonToGrpc 6.10.LocalRespo…

TypeScript 非空斷言

TypeScript 非空斷言 發布于 2020-04-08 15:20:15 17.5K0 舉報 一、非空斷言有啥用 介紹非空斷言前&#xff0c;先來看個示例&#xff1a; function sayHello(name: string | undefined) {let sname: string name; // Error } 對于以上代碼&#xff0c;TypeScript 編譯器…

用戶端Web自動化測試-L1

目錄&#xff1a; Web自動化測試價值與體系環境安裝與使用自動化用例錄制自動化測試用例結構分析web瀏覽器控制常見控件定位方法強制等待與隱式等待常見控件交互方法自動化測試定位策略搜索功能自動化測試用戶端Web自動化測試 1.Web自動化測試價值與體系 功能測試場景: UI 自…

IntelliJ Idea 編譯時控制臺上中文輸出亂碼

猜測原因是IDEA啟動時未指定編碼信息&#xff0c;故與系統編碼保持一致&#xff08;windows中文系統默認為GBK編碼&#xff09;,當以UTF-8編碼進行編譯在控制臺會以GBK編碼輸出,從而導致亂碼 解決方案 指定Idea啟動時JVM的默認編碼為UTF-8 Help -> Edit Custom Options P…

本地圖片的image加密解密-Python 3.10-win10

本地圖片的image加密解密- Python 3.10 pyt3int22 -根據1zip下圖片批量生成加密的-物體識別.py import ioimport os import base64 import json # 指定圖片文件夾 image_dir = "./1zip/" base64code_dir = "./base64code/" base64_to_dir = "./bas…

AUTOSAR規范與ECU軟件開發(基礎篇)2.5 AUTOSAR方法論

前言 AUTOSAR方法論(AUTOSAR Methodology) 中車用控制器軟件的開發涉及系統級、 ECU級和軟件組件級。 系統級主要考慮系統功能需求、 硬件資源、 系統約束, 然后建立系統架構; ECU級根據抽象后的信息對ECU進行配置; 系統級和ECU級設計的同時, 伴隨著軟件組件級的開發。 上…

Sql server還原失敗(數據庫正在使用,無法獲得對數據庫的獨占訪問權)

一.Sql server還原失敗(數據庫正在使用,無法獲得對數據庫的獨占訪問權) 本次測試使用數據庫實例SqlServer2008r2版 錯誤詳細&#xff1a; 標題: Microsoft SQL Server Management Studio ------------------------------ 還原數據庫“Mvc_HNHZ”時失敗。 (Microsoft.SqlServer.…