[回到版面]
回應模式
名 稱
內 文
附加圖檔[] []
  • 可附加圖檔類型:GIF, JPG, JPEG, PNG, WEBM,瀏覽器才能正常附加圖檔
  • 附加圖檔最大上傳資料量為 3072 KB。
  • 當檔案超過寬 125 像素、高 125 像素時會自動縮小尺寸顯示
  • 目前附加圖檔使用量大小: 175965 KB / 500000 KB
  • 回覆時程式碼縮排會被trim消掉,請善用[code][/code]標色或貼到ideone等網站
  • LaTeX記法可以用「$$」或「\( \)」包起來,例如「$\sum_{k=1}^{k=n} k^2 = \frac{n(n+1)(n+2)}{6}$」
  • 投稿時請點擊畫像認證後,再按下 [送出] 按鈕提交。
  • 鬧板、攻擊性發言、煽動性發言請無視(回應者也無視),並使用del或在貓管理部向管理員回報。
  • 新介面尚處於測試階段,如果有任何問題可以向管理員或於程設交流版反映。

檔名:1551790681096.jpg-(34 KB, 600x800)
34 KB
無題無名19/03/05(二)20:58:01 ID:WrY2UMJINo.13022del
static void passValue(double value) {
value = 20.0;
}

static void passReference(Pen reference) {
reference.price = 20.0;
}

public static void main(String[] args) {
double price = 10.0;
passValue(price);
System.out.println(price);

Pen myPen = new Pen();
myPen.price = 10.0;
passReference(myPen);
System.out.println(myPen.price);
}
}

Java
不懂為什麼這邊
double price = 10.0;
passValue(price);
System.out.println(price);

price的輸出值會是10.0 passValue(price)不是應該把上面
宣告的price=10.0覆蓋成20.0了嗎?
無名19/03/05(二)21:00:52 ID:hOVUO5JMNo.13023del
之前綜合再吵JAVA的指標問題
就是在講這件事情
無名19/03/05(二)21:03:11 ID:NnI.4StMNo.13024del
檔名:1551790991992.jpg-(180 KB, 430x3200)
180 KB
無本文
無名19/03/05(二)21:20:09 ID:WrY2UMJINo.13025del
>>13024
如果我的理解沒錯的話
用門牌來比喻就是Pen()記憶體路1號的一間房子
Pen myPen=new Pen();就是在記憶體路2號(或者n號)蓋一間
跟Pen()一模一樣(包含內裝擺設)的新房子 但passrefernce()對
myPen這間新房子的內裝擺設做了改變

但passvalue的部分我看了圖還是不太懂
但是
無名19/03/05(二)21:31:15 ID:WrY2UMJINo.13026del
檔名:1551792675859.png-(18 KB, 1152x648)
18 KB
>>No.13024
如果用這張圖來講 你的意思是passvalue()是住在記憶體路100號
(heap區塊)
同時在Stack區塊創造了一個變數叫value 然後這個value變數儲存
的是記憶體路100號(門牌上的地址) 所以price變數跟value是2個
不同的東西 不會被覆蓋?
無名19/03/05(二)21:55:05 ID:SBoFdaEUNo.13027del
Pen myPen = new Pen();
Java這語法真的很機掰
看起來像是宣告了一個實體 名叫myPen
實際上myPen用法卻是像個address
那不就天生要有new這樣的關鍵字才能建立物件了?

語法不能像這樣嗎?
Pen myPen;
反正指標已經被禁止了
無名19/03/05(二)23:36:00 ID:NnI.4StMNo.13028del
>>13024
等效程式碼
我不善長解釋

public static void main(String[] args) {
double price = 10.0; // 1
double value = price; // 2
value = 20.0; // 3
System.out.println(price); // 4

Pen myPen = new Pen(); // 5
myPen.price = 10.0; // 6
Pen reference = myPen; // 7
reference.price = 20.0; // 8
System.out.println(myPen.price); // 9
}
無名19/03/05(二)23:43:13 ID:hOVUO5JMNo.13029del
無名19/03/06(三)09:57:08 ID:9JVxZVYUNo.13030del
>>13027
>>那不就天生要有new這樣的關鍵字才能建立物件了?

而且new回傳出來的是一個參考

>>語法不能像這樣嗎?
>>Pen myPen;
語法允許這樣寫
意義上是建立一個沒目標的參考
無名19/03/06(三)12:56:28 ID:Fyk4RgvUNo.13031del
為啥會這樣原因很簡單,Pen myPen=new Pen();這段
myPen放在JVM Stack上,new Pen()放在JVM Heap上。
JVM Stack會在你退出該函數作用域(基本上就是函數return)將空間歸還,
JVM Heap會用垃圾蒐集(GC)機制自動清理沒有被參考的資源。
所以Pen myPen是要求JVM在Stack儲存一個Pen的參考,
myPen = new Pen()要求JVM在Heap儲存一個Pen實例並讓myPen參考它,
這樣myPen可以被其他參考隨意複製(Pen reference = myPen;)而他所指向的實例仍然保持有效,
這樣就可以避免會在C++中遇到的參考對象離開函數作用域,該對象被Stack清除造成野指標的問題。
因為你無法在JAVA中製造一個指向Stack上的變數的參考。
(但這也導致了惱人的int[]跟Integer[]的問題...)

如果不明白JVM Stack跟JVM Heap,可以參考:
https://blog.marksylee.com/2016/09/14/java-interview-02-jvm-stack-heap/
無名19/03/06(三)13:24:05 ID:OI80c5k2No.13033del
因為double是primitive type(原始型別)
所以當作參數傳遞時都會直接複製一次

所以你看到的20.0實際上是從10.0複製來的10.0被覆蓋 所以原來的10.0不受影響

在C++也是這樣 但是你可以改成宣告double& value來傳遞指標
就可以覆蓋原值
Java沒有primitive指標操作所以永遠是pass value

第二個passReference Java裡面priimitive type以外所有都是reference type 所以當參數傳遞時一律傳遞指標 所以原值被覆蓋
無名19/03/07(四)10:25:08 ID:.GQK59OkNo.13037del
>>13031
>>這樣就可以避免會在C++中遇到的參考對象離開函數作用域,該對象被Stack清除造成野指標的問題。
C++很早就有shared pointer的概念了
這問題早就解決了
只是拖到C++11才加入標準庫而已

垃圾收集這招在C/C++也是能用的
https://github.com/ivmai/bdwgc

不過與其建造這些功能還是不如像Java一樣設下重重防呆措施
免得工程師亂寫出難解的bug
沒水準的實在太多了
無名19/03/08(五)01:34:32 ID:pEyWQ4XUNo.13039del
>>13037
智能指針不能自動解決野指針的問題,況且在C++11提供move語意之前不能放進STL容器的智能指針就是個垃圾。
當然你可以用RAII或者shared pointer + weak pointer,但就是很麻煩。
用智能指針最大的問題是實際應用上常常需要混用一般指針,這時智能指針的自動清理就爆炸了。
無名19/03/08(五)10:49:18 ID:t8cMnw0ANo.13040del
>>13039
>>況且在C++11提供move語意之前不能放進STL容器的智能指針就是個垃圾。
Why?
std::shared_ptr不是可以隨便丟嗎?
我都拿它搭配vector跟map來使用
需要std::move的不是std::unique_ptr嗎?

而且boost都實作shared_ptr那麼久了
哪裡需要等C++11?

shared_ptr的真正難題是那互鎖現象(還是該稱為遞迴引用?)
一鎖起來就咬著不放了

>>實際應用上常常需要混用一般指針
我也會被迫去使用裸指標
但是規劃好就會很安全
例如:
std::shared_ptr<MyClassA>  A;
std::shared_ptr<MyClassB>  B;
如果B裡面需要使用A的裸指標
而且B會把A的裸指標存到內部成員
那A就需要存一份B的shared_ptr
確保使用期間A都會存在
無名19/03/08(五)21:28:13 ID:mhPn.TaMNo.13041del
檔名:1552051693251.jpg-(103 KB, 690x931)
103 KB
java在設計考量上把pointer拿掉了
所以java沒有所謂的passing by reference.

你的附圖中passValue的method之所以沒有更改為20,
是因為在method建立時就會依parameter劃分記憶體,
複製argument的數值後再去做運算,
所以值做完不會變動。

另外附圖passReference,
再說一次java沒有所謂的passing by reference,
這method是你將parameter設為承接Pen class的object
block裡的程式碼是將承接的object的price field設為20

直接帶有數值的object像是String,Integer,Double...
也是passing by value的如我的附檔範例
無名19/03/08(五)22:18:39 ID:eZw2IuQUNo.13042del
>>13041
雖然你說的我看不懂 但我已經大概弄懂了
我的理解:簡單來說passValue這個method執行完之後
被從10.0改成20.0的那個區域變數value已經消失了
所以實際上sysout的那個price是被宣告為10.0的price
下面那個passReference的區域變數reference跟myPen
都被弄到指向myPen這個物件 所以在passReference裡
面對reference.price做的操作實際上就是在對
myPen.price做操作
無名19/03/09(六)02:14:26 ID:dGdqCL76No.13043del
>>13041
說真的以java實際上的運作來講
實在很難不說那東西根本就是pointer,只是語法上沒有*而已
我認為有這個認識會更容易理解java到底在幹什麼
(前提是要了解C的pointer就是了)
無名19/03/09(六)11:14:46 ID:ohDP7wbUNo.13044del
>>13043
指標的輕便性關係到執行效率
不可能完全移除
只能想辦法去阻止指標的那些危險特性
無名19/03/10(日)23:33:28 ID:.kPudb3ANo.13049del
想請教一下
如果在passValue這個方法裡
去掉void
加上return value
System.out.println(price); 會變成20.0嗎?

另想請教C#的問題

JAVA 沒有指標
(passing by value 傳值)

C++ 有指標
(passing by value 傳值)
(passing by reference(pointer) 傳參考(指標))

C# 可以用unsafe識別字開啟指標
(passing by value 傳值)
(passing by reference(pointer) 傳參考(指標))

passing by address 好像等於 passing by reference?

所以C#也是像C++一樣可以選擇要不要用指標?
還是C#是用別種方式?
這部分有點弄不懂,不知道這樣是否有理解錯誤?
無名19/03/11(一)00:31:35 ID:hAsfOLtQNo.13050del
>>13049
>>System.out.println(price); 會變成20.0嗎?
不會
除非你price=passValue(price);
無名19/03/11(一)13:41:47 ID:zH5yTorsNo.13051del
>>13049
C#有個ref關鍵字
passReference(ref int arg) { arg = 20; }

int value = 10;
passReference(ref value);
Console.WriteLine(value); // 20
無名19/03/12(二)22:34:45 ID:Uoa0gHMANo.13052del
檔名:1552401285981.jpg-(64 KB, 650x454)
64 KB
只是閱讀方式的問題
無名19/03/12(二)22:35:31 ID:Uoa0gHMANo.13053del
檔名:1552401331475.jpg-(65 KB, 299x236)
65 KB
>>13052
寫個JAVA還在那邊底層來底層去,JAVA的設計者都要哭了。
無名19/03/12(二)22:38:56 ID:Uoa0gHMANo.13054del
檔名:1552401536601.png-(84 KB, 500x296)
84 KB
>>13051
Ref是好東西沒錯,不過MSDN也說了,若沒必要不要使用。

現在也可以直接回傳Tuple結果,或是直接DTO拋轉。
無名19/03/12(二)22:58:33 ID:Uoa0gHMANo.13055del
檔名:1552402713808.png-(243 KB, 1080x768)
243 KB
>>13054
重新看一下MSDN,不建議的部分好像拿掉了。

以為是我精神錯亂了重新GOOGLE,確認他曾經"不建議"過,看來我神智還很清楚。

https://home.gamer.com.tw/creationDetail.php?sn=3837690
https://codeday.me/bug/20180108/115804.html
無名19/03/14(四)00:24:27 ID:3tKkqLf.No.13061del
>>13055

有點好奇這段轉折是怎麼發生的,最新的C#有把哪邊改掉了嗎?
之前第一次看到這東西的時候有驚訝一下但是看到〝建議重新審
視程式架構〞縮了。
無名19/03/14(四)21:00:05 ID:P/63Z4B2No.13062del
檔名:1552568405654.png-(59 KB, 414x248)
59 KB
>>13061
也許是他們在最近的C#版本中把不安全有疑慮的部分給移除了。
*有注意到他們針對C#7.0有寫修改
https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/classes-and-structs/ref-returns
>從 C# 7.0 開始,C# 支援參考傳回值 (ref 傳回值)


【刪除文章】[]
刪除用密碼: