[問題] 關於c++11 ctor行為
看板C_and_CPP (C/C++)作者a58524andy (a58524andy)時間7年前 (2018/06/23 18:10)推噓6(7推 1噓 43→)留言51則, 9人參與討論串1/2 (看更多)
開發平台(Platform): (Ex: Win10, Linux, ...)
win10 1803 WSL@Debian
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
c++11
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
<iostream>
問題(Question):
有兩個相似的case,煩請參照外部連結閱讀;編譯以及執行的選項如下
$ g++ -c my_PTT_post.cc --std=c++11 -O0 -Wall -fno-elide-constructors
$ g++ -o test my_PTT_post.o
$ ./test
想要使用這些編譯選項以免除NRVO/RVO,方便觀察ctor呼叫行為
兩個case的差異僅在於
// case1,pass by value
myClass g (myClass other);
// case2,pass by rvalue reference
myClass g (myClass&& other);
以下是case1的結果以及個人的理解 (myClass g( myClass other ); )
ctor // ctor without parameter inside function f
mv ctor // returned object of f steal the rvalue created by ctor
mv ctor // obj1 steal RHS of "=" sign; RHS is a rvalue expression
ctor // ctor without parameter inside function f inside function g
mv ctor // returned object of f steal the rvalue created by ctor
mv ctor // parameter of g steal what returned by f, which is rvalue
inside g // now inside function g
mv ctor // returned object of g steal the glvalue in g,
which is at the end of its lifespan
mv ctor // obj2 steal RHS of "=" sign, which is a rvalue expression
以下是case2的結果以及個人的理解 (myClass g( myClass&& other ); )
ctor // ctor without parameter inside function f
mv ctor // returned object of f steal the rvalue created by ctor
mv ctor // obj1 steal RHS of "=" sign; RHS is a rvalue expression
ctor // ctor without parameter inside function f inside function g
mv ctor // returned object of f steal the rvalue created by ctor
inside g // g takes rvalue reference, so we step into g directly
cp ctor // returned object of g is a copy of the rvalue reference in g
mv ctor // obj2 steal RHS of "=" sign; RHS being a rvalue expression
不懂的地方有2:
1. operator =以及obj1/obj2原本自己的ctor怎麼都沒有被呼叫呢?
還是case1、case2當中(應該要)呼叫ctor without parameter以及operator =的寫法
myClass obj1 = f();
myClass obj2 = g(f());
實際上等同沒有用到ctor w/o parameter、operator =,僅用到mv/cp ctor
myClass obj1(f());
myClass obj2(g(f()));
的這個寫法呢?
2. case2當中,最後有一個copy ctor被呼叫了
這個copy ctor應該是為了把g吃進來的rvalue reference return回外面
但是為甚麼需要用到copy ctor呢?
除非使用者故意用了std::move()把expression轉成rvalue丟進g
不然這個reference所代表的東西應該會是馬上就要過期的rvalue
一般情況下如同case1呼叫mv ctor可以省一些資源吧?
餵入的資料(Input):
nope
預期的正確結果(Expected Output):
如問題描述
錯誤結果(Wrong Output):
應該是我有哪裡搞錯了QQ
程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔)
case1:
https://godbolt.org/g/hBX1yw
case2:
https://godbolt.org/g/nXqyYc
補充說明(Supplement):
煩請各位指點 m(_ _)m
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.233.88.219
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1529748654.A.1FC.html
→
06/23 18:50,
7年前
, 1F
06/23 18:50, 1F
噓
06/23 20:25,
7年前
, 2F
06/23 20:25, 2F
→
06/23 20:26,
7年前
, 3F
06/23 20:26, 3F
→
06/23 20:26,
7年前
, 4F
06/23 20:26, 4F
→
06/23 20:27,
7年前
, 5F
06/23 20:27, 5F
→
06/23 20:28,
7年前
, 6F
06/23 20:28, 6F
→
06/23 20:28,
7年前
, 7F
06/23 20:28, 7F
→
06/23 20:29,
7年前
, 8F
06/23 20:29, 8F
→
06/23 20:30,
7年前
, 9F
06/23 20:30, 9F
→
06/23 20:30,
7年前
, 10F
06/23 20:30, 10F
→
06/23 20:30,
7年前
, 11F
06/23 20:30, 11F
→
06/23 20:32,
7年前
, 12F
06/23 20:32, 12F
→
06/23 20:32,
7年前
, 13F
06/23 20:32, 13F
推
06/23 20:37,
7年前
, 14F
06/23 20:37, 14F
→
06/23 20:41,
7年前
, 15F
06/23 20:41, 15F
→
06/23 20:42,
7年前
, 16F
06/23 20:42, 16F
→
06/23 20:42,
7年前
, 17F
06/23 20:42, 17F
我以為已經關掉RVO了耶
參照 https://goo.gl/3D5p3x
有在編譯選項加 -fno-elide-constructors
根據內文貼的code連結,比較了一下問題一提到的兩種寫法產生的組語
(編譯選項同內文所提)
發現main裡面的組語一模一樣
因此這部份結果應該如藍魂、神崎亞莉亞所提
compiler對於兩種寫法的處理方式是一樣的
這裡( https://stackoverflow.com/a/8777310 )的回答也認為compiler是這樣處理的
不過還是不太懂問題二的部份
甚麼情況下編譯器會決定用mv ctor來把東西傳回外界
又是甚麼時候會決定優先採用cp ctor啊?
※ 編輯: a58524andy (36.233.88.219), 06/23/2018 22:06:24
→
06/24 01:09,
7年前
, 18F
06/24 01:09, 18F
推
06/24 01:19,
7年前
, 19F
06/24 01:19, 19F
→
06/24 01:25,
7年前
, 20F
06/24 01:25, 20F
推
06/24 03:46,
7年前
, 21F
06/24 03:46, 21F
推
06/24 06:20,
7年前
, 22F
06/24 06:20, 22F
→
06/24 06:27,
7年前
, 23F
06/24 06:27, 23F
→
06/24 06:45,
7年前
, 24F
06/24 06:45, 24F
→
06/24 06:45,
7年前
, 25F
06/24 06:45, 25F
→
06/24 06:46,
7年前
, 26F
06/24 06:46, 26F
→
06/24 06:48,
7年前
, 27F
06/24 06:48, 27F
→
06/24 06:48,
7年前
, 28F
06/24 06:48, 28F
→
06/24 07:04,
7年前
, 29F
06/24 07:04, 29F
→
06/24 07:06,
7年前
, 30F
06/24 07:06, 30F
推
06/24 07:34,
7年前
, 31F
06/24 07:34, 31F
→
06/24 07:37,
7年前
, 32F
06/24 07:37, 32F
→
06/24 07:37,
7年前
, 33F
06/24 07:37, 33F
→
06/24 07:53,
7年前
, 34F
06/24 07:53, 34F
推
06/24 07:58,
7年前
, 35F
06/24 07:58, 35F
→
06/24 07:59,
7年前
, 36F
06/24 07:59, 36F
→
06/24 08:00,
7年前
, 37F
06/24 08:00, 37F
推
06/24 08:45,
7年前
, 38F
06/24 08:45, 38F
→
06/24 08:46,
7年前
, 39F
06/24 08:46, 39F
→
06/24 08:46,
7年前
, 40F
06/24 08:46, 40F
→
06/24 08:46,
7年前
, 41F
06/24 08:46, 41F
→
06/24 08:47,
7年前
, 42F
06/24 08:47, 42F
→
06/24 08:47,
7年前
, 43F
06/24 08:47, 43F
→
06/24 08:47,
7年前
, 44F
06/24 08:47, 44F
→
06/24 10:40,
7年前
, 45F
06/24 10:40, 45F
→
06/24 10:40,
7年前
, 46F
06/24 10:40, 46F
→
06/24 11:06,
7年前
, 47F
06/24 11:06, 47F
→
06/24 11:06,
7年前
, 48F
06/24 11:06, 48F
→
06/24 11:06,
7年前
, 49F
06/24 11:06, 49F
→
06/24 11:07,
7年前
, 50F
06/24 11:07, 50F
→
06/24 11:08,
7年前
, 51F
06/24 11:08, 51F
感謝推文各位
稍微整理對於回答二的意見如下
參考firose的連結
在case2中 // myClass g (myClass&& other);
在g函式裡面 吾人不能直接把"other"這個expression當成rvalue看待
否則"other"這個expression在g呼叫其他函式的時候容易被玩壞
同時參考n3337 https://goo.gl/SXrM4E ch.5 pg.97 note.6
"an expression is an xvalue if it is [...] a cast to rvalue reference to
object type,"
"other"這個expression在g裡面應該被當成一個xvalue使用
至於這個xvalue expression傳回時的行為則如loveflames所提
實際上"other"還是一個reference而不是一個non-static object
因此採用了cp ctor而沒有採用mv ctor
如果有錯的話煩請不吝指正@@
※ 編輯: a58524andy (36.233.88.219), 06/24/2018 16:52:45
討論串 (同標題文章)
完整討論串 (本文為第 1 之 2 篇):
6
51
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章