左值、右值與右值引用 & C++11中
在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、沒有名字的就是右值。
舉個例子:在a=b+c;中,&a是允許的操作,但&(b+c)這樣的操作則不會通過編譯。因此a是一個左值,(b+c)是一個右值。
其次,在C++11中右值又分為將亡值(xvalue,eXpiring Value)和純右值(prvalue,Pure Rvalue)。
其中純右值的概念等同於我們在C98標準中所謂的右值概念,講的是用於辨識臨時變數和一些不跟物件關聯的值
比如class a{...};a fun(){...}函式返回的臨時例項,比如a=1+3;中1+3產生的臨時變數值,再比如a=true;中的true,上述這些都是純右值。
而將亡值是C++11中新提出的一個概念。
這裡讀者最關心的應該是兩個問題:1.將亡值概念的提出是為了解決什麼問題?2.將亡值的定義到底是什麼?
我們來從問題的起源一步步講起,希望在最後解答這兩個問題。
大家都知道,C++中一般函式或方法的實參以及返回值都是以副本的形式傳遞的(除非你特別指定了按引用來傳遞,而這也僅限於實參)。
來看一段程式碼
#include <iostream>
using namespace std;
class A
{
public:
//建構函式(初始化p_int,並附上i的值)
A(int i)
{
p_int=new int(i);
cout<<"call A(int i)"<<endl;
}
//==============================
//拷貝建構函式(對p_int實現了深拷貝)
A(const A &a)
{
p_int=new int(*(a.p_int));
cout<<"call A(const A &a)"<<endl;
}
//==============================
//解構函式(釋放p_int)
~A()
{
cout<<"call ~A()"<<endl;
delete p_int;
}
//==============================
int *p_int;
};
//傳入一個A物件,並直接返回該物件
A fun(A a){return a;}
int main()
{
A test(10);
fun(test);
return 1;
}
執行結果
![](http://www.verycto.com/uploads/151010/20151030_1.png)
首先我們關閉了g++編譯器的自動優化功能,來看到c++最本質的執行狀態,關閉自動優化的引數是-fno-elide-constructors。
因為A test(10);程式碼,是我們呼叫了A的普通建構函式,獲得了螢幕輸出call A(int i)。
因為將test傳入fun()中使用了按副本傳遞,所以呼叫了A的拷貝建構函式,獲得了螢幕輸出call A(const A &a)。
因為fun()中的return a;也是按副本傳遞的,所以再一次的呼叫了A的拷貝建構函式,獲得了螢幕輸出call A(const A &a)。
至此程式執行的螢幕輸出應該是清晰且沒有任何疑問的。
同時由於類的成員涉及指標型別,所以我們的拷貝建構函式使用了深拷貝。
在這段程式碼中,我只顯性的建立了一次A的物件,但是卻產生了巨大的開銷。
為p_int開闢記憶體就達3次之多,如果是實際身材環境中,真實的類可能包含更多的成員涉及更多的記憶體。
我們仔細思考一下,兩次拷貝建構函式的呼叫都是由於程式產生了一個副本導致的。
而這些副本物件其實並沒有任何實際意義,而且轉瞬即逝,在完成了自己的傳遞任務後就即可銷燬了。這恰恰和將亡值想要表達的意思十分吻合,不是嗎?
第一個問題似乎已經有了答案,但將亡值的概念能為我們解決實際問題呢?
如果已經可以明確,我的拷貝源是一個將亡值,那麼我們其實並沒有深拷貝的必要,而是隻要將他的資源移位即用就可以。
所以C++11提供了一個所謂的移動建構函式,接受一個將亡值作為拷貝源。
來看一段程式碼
#include <iostream>
#include <iostream>
using namespace std;
class A
{
public:
//建構函式(初始化p_int,並附上i的值)
A(int i)
{
p_int=new int(i);
cout<<"call A(int i)"<<endl;
}
//==============================
//拷貝建構函式(對p_int實現了深拷貝)
A(const A &a)
{
p_int=new int(*(a.p_int));
cout<<"call A(const A &a)"<<endl;
}
//==============================
//移動建構函式(把將亡值的指標據為己用)
A(A &&a):p_int(a.p_int)
{
a.p_int=nullptr;
cout<<"call A(A &&a)"<<endl;
相關推薦
左值、右值與右值引用 & C++11中
我們先來談談C++11中對左右值的判斷標準,以及左右值本身的一些細節,我想這應該是故事的開始。
在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、沒有名字的就是右值。
舉個例子:在a=b+c;中,&a是允許的操作,但&(b+c)這樣的操
執行緒與互斥鎖(C++11中std::thread和std::mutex的用法)
執行緒
0
首先是曾經在MultiCMOS專案中用到的:
#include <thread> //包含標頭檔案
class IDataProcessUnit
{
protected:
c++11 中的右值引用、 move 、 forward
再次來寫左值右值相關的東西我的內心是十分惴惴不安的,一來這些相關的概念十分不好理解,二來網上相關的文章實在太多了,多少人一看這類題目便大搖其頭,三來也怕說不清反而誤導了別人,反覆糾纏這些似乎無關大雅的語言細節實在也有成為 language lawyer 之嫌。但我還是決定再總結一次,因為這是我一直以來學習新
對C++11中的`移動語義`與`右值引用`的介紹與討論
本文主要介紹了C++11中的移動語義與右值引用, 並且對其中的一些坑做了深入的討論. 在正式介紹這部分內容之前, 我們先介紹一下rule of three/five原則, 與copy-and-swap idiom最佳實踐.
本文參考了stackoverflow上的一些回答. 不能算是完全原創
rule
Effective C++筆記之一:宣告、定義、初始化與賦值
一.宣告(Declaration) 區分宣告和定義可以讓C++支援分開編譯,宣告常常見於標頭檔案中。原始檔包含標頭檔案之後,就可以使用這個變數,即使沒有看到該變數的定義。 宣告的語法如下: extern int i; // object decl
Python中賦值、淺拷貝與深拷貝的區別
賦值,其實就是物件的引用,對新物件的如何修改都會影響到原始物件。
Python中有兩種拷貝操作:淺拷貝和深拷貝。
copy.copy(x):返回x的淺拷貝。
copy.deepcopy(x):返回x的深拷貝。
那麼都是拷貝,淺拷貝和深拷貝有什麼不同嗎?
淺
C 判斷 —— if...else 語句(bool變數、float變數、指標變數與“零值”進行比較)(else 到底與哪個 if 配對呢? if 語句後面的分號?)
1、bool 變數與“零值”進行比較
bool 變數與“零值”進行比較的 if 語句怎麼寫?
bool bTestFlag = FALSE;//想想為什麼一般初始化為 FALSE 比較好?
A), if(bTestFlag == 0); if(bTestFlag == 1
python 分詞、自定義詞表、停用詞、詞頻統計與權值(tfidf)、詞性標註與部分詞性刪除
# -*- coding: utf-8 -*-
"""
Created on Tue Apr 17 15:11:44 2018
@author: NAU
"""
##############分詞、自定義詞表、停用詞################
import jieba
C++拷貝構造、移動構造與返回值優化
拷貝建構函式
拷貝建構函式(又稱複製建構函式),是用來建立已存在物件的副本。對應的還有一個概念是拷貝賦值運算子,當需要顯示地宣告拷貝建構函式時,一般建議同時宣告拷貝賦值運算子,以使得程式碼的含義明確。
如果不宣告拷貝建構函式(或拷貝賦值運算子),編譯器將會生一個預設的
C++11中的universal引用和右值引用
stackoverflow上有個問題:Why “universal references” have the same syntax as rvalue references? 就是說為什麼這倆的形式都是T&&(T表示一個型別)。其中有一個回答很
2.1詳解變數的定義、初始化與賦值
在前的課程中我們談到,變數其實就是一塊記憶體空間的名稱。簡要地說,計算機擁有可供程式使用的隨機存取儲存器(RAM),當一個變數被定義時,一部分記憶體就會被預留給這個變數。
記憶體的最小單位是二進位制數字(binary digit,bit,位元),0或者1。你可以把bi
c++ 11中emplace_back替代push_back的相關知識點,含右值引用,move用法等
C++11引入了右值引用,轉移建構函式,push_back()右值時就會呼叫建構函式和轉移建構函式(原來是呼叫拷貝構造,會為臨時變數申請堆空間,影響程式效率,C++11以後為右值引用呼叫轉移建構函式,不會為臨時變數申請堆空間,而是直接賦值,提高程式效率)。 使用mplace_back替代push_back()
【Python】關於鍵盤鍵入值、str的與或非問題?【報錯:TypeError: unsupported operand type(s) for |: 'str' and 'str'】
error 運算符 字符 符號 str == 條件 col one 參考
【報錯:TypeError: unsupported operand type(s) for |: ‘str‘ and ‘str‘】
在進行鍵入值比較的時候,想要用“或&rd
js物件的直接賦值、淺拷貝與深拷貝
最近Vue專案中寫到一個業務,就是需要把對話方塊的表單中的資料,每次點選提交之後,就存進一個el-table表格中,待多次需要的表單資料都提交進表格之後,再將這個表格提交,實現多個表單資料的同時提交,期間還可以用表格進行預覽、修改等其他操作。將每個表單資料存進表格的程式碼大致程式碼如下:
let&
ForkJoin有參無返回值、有參有返回值實例
.com turn sys int dao tps end 並且 ota 介紹:
a . Fork/Join為JKD1.7引入,適用於對大量數據進行拆分成多個小任務進行計算的框架,最後把所有小任務的結果匯總合並得到最終的結果
b . 相關類
public abst
vue學習十一(prop傳不同值、 v-bind 動態賦值、單向資料流、prop校驗)
區域性註冊
在這些情況下,你可以通過一個普通的 JavaScript 物件來定義元件:
var ComponentA = { /* ... */ }
然後在 components 選項中定義你想要使用的元件:
new Vue({
el: '#app',
MySQL開發技巧 第二禪(子查詢中匹配兩個值、解決同屬性多值過濾的問題、計算累進稅的問題)
一、如何在子查詢中匹配兩個值
mysql子查詢的使用場景及其好處
1、什麼是子查詢?
Vue.js實現雙向資料繫結(表單自動賦值、表單自動取值)
1、使用Vue.js實現雙向表單資料繫結,例子
<!--html程式碼-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta
【Android基礎】頁面跳轉與傳值(Activity跳轉與傳值)
一個Android應用程式很少會只有一個Activity物件,如何在多個Activity之間進行跳轉,而且能夠互相傳值是一個很基本的要求。
本次我們就講一下,Android中頁面跳轉以及傳值的幾種方式!
Activity跳轉與傳值,主要是通過Intent類來連線多個A
Vue(2)- v-model、局部組件和全局組件、父子組件傳值、平行組件傳值
star component handle lec 開發 div 復制 line 定義
一、表單輸入綁定(v-model 指令)
可以用 v-model 指令在表單 <input>、<textarea> 及 <select> 元素上