亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 引用變量占用內(nèi)存空間嗎? [打印本頁]

作者: go_hao    時(shí)間: 2011-07-30 18:31
標(biāo)題: 引用變量占用內(nèi)存空間嗎?
本帖最后由 go_hao 于 2011-07-30 18:33 編輯

引用變量占用內(nèi)存空間嗎?它的內(nèi)存地址就是“別引用的那個(gè)變量”呀,難道他自己不占內(nèi)存嗎?

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
        int val1=99;
        int &val2=val1;

        cout << "val1:" << val1 << " address:" << &val1 << endl;
        cout << "val2:" << val2 << " address:" << &val2 << endl;
        return 0;
}


引用變量,就是“被引用變量”的別名,但是,我不理解,它是否占內(nèi)存呢?
不可能不占內(nèi)存空間呀,但是如果占內(nèi)存的話,為何它的內(nèi)存地址,與被引用的變量是一個(gè)地址呢?
作者: hellioncu    時(shí)間: 2011-07-30 21:46
編譯好后,引用就沒了
作者: dewade    時(shí)間: 2011-07-31 09:57
引用就是別名,只是另外一個(gè)名字讓你好識(shí)別之類的吧,實(shí)際上不占內(nèi)存的。
作者: dewade    時(shí)間: 2011-07-31 09:58
主要應(yīng)該是用于簡(jiǎn)化一些復(fù)雜的變量名之類的吧。
作者: OwnWaterloo    時(shí)間: 2011-07-31 13:00
引用不占空間的說法是流傳很廣的誤會(huì)…… 造成該誤會(huì)的原因可能有:

1. 自動(dòng)變量?jī)?yōu)化

int是否占用空間?  這個(gè)不好說, 但int能sizeof, 能用 & 取到地址(非register)是肯定的。

  1. int f(int x, int y) {
  2.       int xx = x*x;
  3.       int yy = y*y;
  4.       int a = xx + yy;
  5.       return a;
  6. }
復(fù)制代碼
xx,yy,a是否占空間?  優(yōu)化開高了也許就不占了, 直接寄存器干活。
x/y是否占空間? 至少i386上 cdecl 調(diào)用約定是占的。


2. 無法取得變量本身的地址

sizeof得到的是被引用對(duì)象的大小, & 得到的是被引用對(duì)象的地址。
因?yàn)橐谜Z意的關(guān)系, 沒辦法"直接"獲得引用變量本身的大小與地址信息
可能也造成了該誤會(huì)……


類似Windows下的dll導(dǎo)入機(jī)制:

  1. __declspec(dllimport) double x;
復(fù)制代碼
實(shí)際上類似這樣的代碼

  1. extern double* __imp_x;
  2. #define x (*__imp_x);
復(fù)制代碼
通過x宏, 沒法取得 __imp_x 的大小與地址。
C++沒有規(guī)定引用如何實(shí)現(xiàn)。 但在i386上, cl/gcc/clang實(shí)現(xiàn)都類似這樣。


3. 繞過語法糖干擾

最簡(jiǎn)單的方法:

  1. struct X { double& d; };
  2. enum { size = sizeof(X) }; // 該平臺(tái)上引用大小

  3. double d;
  4. X x = { d };
  5. void* address = &x; // 引用變量的地址

  6. unsigned char representation[sizeof(X)];
  7. memcpy(representation, address, sizeof x); // 可查看引用變量的表示
復(fù)制代碼
其他還有很多方法阻止編譯器優(yōu)化, 比如參數(shù), 靜態(tài)變量…… 不過都比結(jié)構(gòu)體復(fù)雜。


4. 小結(jié)

C++ (印象中)沒有詳細(xì)描述引用變量的實(shí)現(xiàn)方式。
但在 i386(cl/gcc/clang) 下, 引用 —— 如同 int —— 是有大小的, 可以用 3 的方式得到
自動(dòng)變量的空間(無論是否是引用)都有可能被優(yōu)化。
作者: txdgtwpv    時(shí)間: 2011-07-31 15:37
不占吧,指針還得留著賦值,引用直接就是別名了
作者: ecjtubaowp    時(shí)間: 2011-07-31 21:47
都有一個(gè)作用域吧。
作者: captivated    時(shí)間: 2011-08-02 11:57
回復(fù) 5# OwnWaterloo


    你妹,很久沒見你上來了啊.

    以前看過幾集《銀他媽》,沒注意。最近追《銀他媽》TV動(dòng)畫,才發(fā)現(xiàn)你的頭像原來是神樂{:3_185:}
作者: andysun1986    時(shí)間: 2011-08-02 15:43
聽說不占
作者: liwangli1983    時(shí)間: 2011-08-02 16:40
占吧。。。做為函數(shù)形參的時(shí)候。。。
作者: captivated    時(shí)間: 2011-08-02 17:46
回復(fù) 10# liwangli1983


    我也認(rèn)為是這樣的。作為函數(shù)形式參數(shù)的時(shí)候,其底層實(shí)現(xiàn)實(shí)際上是指針實(shí)現(xiàn)。所以引用也會(huì)占據(jù)空間(在運(yùn)行棧幀上)。

    但是作為全局引用的時(shí)候,編譯器可以將別名直接替換成實(shí)際的對(duì)象地址。對(duì)于全局變量的維護(hù)發(fā)生在編譯期,因此編譯器可以采取任何方案。所以全局引用是不占空間的。
作者: OwnWaterloo    時(shí)間: 2011-08-03 01:00
回復(fù) 8# captivated

哈, 如果沒看那集, 估計(jì)我也想不到這是那個(gè)毒舌大胃腹黑扣鼻女……

上來干嘛呢……

覺得這個(gè)帖子:
1. 諸多回復(fù)可看出果然誤會(huì)很廣
2. 不同于oop/coding style那樣, 各自有各自的看法。 這屬于一個(gè)一是一二是二的問題, 沒什么好爭(zhēng)論的。
所以就回了一下。

但其實(shí)作用不大, 誤會(huì)的依然誤會(huì)……  所以, 上來干嘛呢……
來看苦逼程序員抱怨苦逼人生嗎?


最后:

  1. int var = 12;
  2. static int& ref = var;
  3. int main(void) {
  4. #ifndef REF
  5.       return var;
  6. #else
  7.       return ref;
  8. #endif
  9. }
復(fù)制代碼
cl -W3 -O1 draft.cpp -link -nodefaultlib -entry:main

只列出重要信息
dumpbin -headers -disasm draft.exe
            1000 entry point (00401000)    // main函數(shù)
   .text name
       6 virtual size
  00401000: A1 00 20 40 00     mov         eax,dword ptr ds:[00402000h] ; 這是直接訪問變量
  00401005: C3                 ret
   .data name
       8 virtual size  // 8字節(jié), 引用變量依然存在


cl -DREF -W3 -O1 draft.cpp -link -nodefaultlib -entry:main
除了如下的匯編代碼, 其他信息同上
  00401000: A1 04 20 40 00     mov         eax,dword ptr ds:[00402004h] ; 這兩行是通過指針訪問變量
  00401005: 8B 00              mov         eax,dword ptr [eax]
  00401007: C3                 ret


gcc -Wall -O1 -fomit-frame-pointer -nostdlib -s draft.cpp -Dmain=entry

dumpbin -headers -disasm a.exe
            1000 entry point (00401000)
   .text name
      1C virtual size
  00401000: A1 00 20 40 00     mov         eax,dword ptr ds:[00402000h]
  00401005: C3                 ret
SECTION HEADER #2
   .data name
       8 virtual size

gcc -DREF -Wall -O1 -fomit-frame-pointer -nostdlib -s draft.cpp -Dmain=entry

同樣, 只有產(chǎn)生的代碼不同
  00401000: A1 04 20 40 00     mov         eax,dword ptr ds:[00402004h]
  00401005: 8B 00              mov         eax,dword ptr [eax]
  00401007: C3                 ret


我想說的只是: 至少在我用過的編譯器(cl/gcc/icc/clang)以及i386上, 引用都是有大小的, 引用的語意需要間接的獲取這個(gè)信息。
后面的一些結(jié)論就越來越無聊了……
依然是這些平臺(tái), 函數(shù)參數(shù)是肯定占空間的; 自動(dòng)變量經(jīng)常被優(yōu)化。
靜態(tài)引用變量這問題真比較無聊……   是這個(gè)結(jié)果也好, 不是也罷……
印象中我還真沒寫過"通過引用(而非直接)訪問靜態(tài)變量"這種代碼……
作者: AD8018    時(shí)間: 2011-08-03 01:11
引用可以放 struct 里的,所以必須占空間

struct A
{
     int &r;
};
作者: captivated    時(shí)間: 2011-08-03 10:00
回復(fù) 12# OwnWaterloo


    呃. 那個(gè)確實(shí)。

    這個(gè)回復(fù)算是解決了我的疑惑~ 話說,cl的那些編譯選項(xiàng)我就沒見過, 或者說我根本沒怎么用過cl...
    gcc的那些編譯選項(xiàng)也不知道神馬意思. 看來, 花時(shí)間認(rèn)真學(xué)習(xí)下gcc和各種binary tools的manual確實(shí)是必要的...

    我覺得g++生成的匯編碼比較難懂,不是因?yàn)锳T&T語法格式的問題, 比如cc編譯C代碼生成的匯編碼, 還是比較容易明白的, 至少棧幀結(jié)構(gòu)神馬的很容易看出來...
    可是因?yàn)镃++引入異常機(jī)制之后,g++需要在函數(shù)棧幀結(jié)構(gòu)上加入支持異常機(jī)制的相關(guān)信息吧,相對(duì)來說比較復(fù)雜. 我對(duì)gas(as)還不夠熟悉吧...

    比如,我寫個(gè)只反映一層函數(shù)調(diào)用的代碼,simple.c:
   
   
    gcc -S simple.c -o simpleC.asm:
   
    嗯,那個(gè)棧幀結(jié)構(gòu)還是很清楚滴...

    g++ -S simple.c -o simpleCPP.asm:
   
    _Z3addii, 我知道你就是add的馬甲,別裝了.
    .LFB0是神馬? .LFE0是神馬?
    .LFB1是神馬? .LFE1是神馬?
   
    毫無疑問, .LFB和.LFE應(yīng)該是g++為支持異常機(jī)制在基本棧幀結(jié)構(gòu)上增加的料. 問題是我對(duì)C++的異常處理了解甚少,所以不了解這些加的料都怎么弄的,以及什么意思...
    扯一下... 關(guān)于cfront. cfront是把C++代碼編譯處理成C代碼的編譯器, C代碼再由C編譯器轉(zhuǎn)換為匯編碼. 那這種 C++ source code -> cfront -> C compiler -> ...的處理方式,毫無疑問是無法在匯編碼級(jí)別往棧幀上加料的(因?yàn)镃語言的函數(shù)棧幀結(jié)構(gòu),編譯出來就那樣子),所以, cfront是無法實(shí)現(xiàn)異常處理機(jī)制的,沒法stack unwind... 或者說... 使用cfront這種方式非常難以實(shí)現(xiàn)異常處理機(jī)制(要做到平臺(tái)體系無關(guān)是吧, 不能寫個(gè)setjump之類的庫(kù)就算是吧...)... 不知這個(gè)扯得對(duì)否?...

    OwnWaterloo兄, 這個(gè)...神馬時(shí)候講下g++的異常處理呢(呃C++的異常處理才對(duì)吧...)? 那個(gè).LFB和.LFE若有研究, 望告知, 求解惑~
作者: zengit    時(shí)間: 2011-08-03 11:47
回復(fù) 14# captivated
http://baiy.cn/doc/cpp/inside_exception.htm   只提供鏈接,還沒到檔次去學(xué)習(xí)
作者: dewade    時(shí)間: 2011-08-03 23:03
看到頭暈了。
作者: OwnWaterloo    時(shí)間: 2011-08-08 18:53
回復(fù) 14# captivated

只研究過Windows下的, 而且忘得差不多了……
建議不單看-S的輸出, 有時(shí)候需要看鏈接后的輸出才行……
作者: xiaoguizi007    時(shí)間: 2011-09-08 18:09
留個(gè)座位,去接老婆去了。
作者: 幻の上帝    時(shí)間: 2011-09-08 18:41
本帖最后由 幻の上帝 于 2011-09-08 18:42 編輯

不是unspecified么。就是說不管占不占,哪怕同一個(gè)程序中在一個(gè)地方占了另一個(gè)地方不占都是合理的。

ISO C++03 8.3.2/3 & ISO C++0x(N3242) 8.3.2/4
It is unspecified whether or not a reference requires storage (3.7).
作者: OwnWaterloo    時(shí)間: 2011-09-08 21:23
回復(fù) 19# 幻の上帝

所以我一直想避免說它是否占空間……  而是說它有大小……
比如5樓的例子, 那些局部變量就很難說是否占空間, C++肯定不會(huì)去做這方面的規(guī)定。
而且, 相對(duì)于一般的局部變量, 引用變量還無法取得引用變量的地址, 更容易優(yōu)化。
作者: 幻の上帝    時(shí)間: 2011-09-08 21:37
本帖最后由 幻の上帝 于 2011-09-08 21:41 編輯
回復(fù)  幻の上帝

所以我一直想避免說它是否占空間……  而是說它有大小……
比如5樓的例子, 那些局部變 ...
OwnWaterloo 發(fā)表于 2011-09-08 21:23


可能各人理解的意思有點(diǎn)不一樣……不過我還是傾向于照字面理解。
說它占空間,或者說具有存儲(chǔ),是不強(qiáng)調(diào)究竟占內(nèi)存還是占寄存器的……(register不也是算storage class specifier么。)這樣就沒問題了吧。
總結(jié):
引用可以占空間,只不過沒法通過常規(guī)訪問對(duì)象的方式對(duì)它的內(nèi)容進(jìn)行操作,但可以包裝成對(duì)象后轉(zhuǎn)換類型來繞過這個(gè)限制;
占了空間的引用和對(duì)象一樣可能從內(nèi)存中被優(yōu)化掉放到寄存器中;
對(duì)于某些引用可能在編譯期確定它自身的內(nèi)容,那么運(yùn)行時(shí)就不占空間(不算代碼段之類)。
作者: davelv    時(shí)間: 2011-09-08 21:44
回復(fù) 8# captivated


神樂打著小花傘的那集。
作者: OwnWaterloo    時(shí)間: 2011-09-08 21:55
回復(fù) 21# 幻の上帝

總結(jié)全部同意。
那么, "引用是否占空間" 與 ISO 中的 unspecified 又如何理解?
我的感覺就是說了等于沒說……
作者: cppfans6    時(shí)間: 2011-09-08 22:07
回復(fù) 1# go_hao


    引用就是別名,其實(shí)都指向一個(gè)東西,不占內(nèi)存。




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2