• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-90  評論-947  文章-0  trackbacks-0
             

            3.10 Lvalues and rvalues [basic.lval]

            左值和右值

            1 Every expression is either an lvalue or an rvalue.

            表達式不是左值就是右值。

            2 An lvalue refers to an object or function. Some rvalue expressions—those of class or cv-qualified class type—also refer to objects. 47)

            左值是指一個對象或者函數。某些右值(那些帶或不帶cv限定符的類類型)也是對象。

            3 [Note:
            some built-in operators and function calls yield lvalues. [Example: if E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the function
            int& f();
            yields an lvalue, so the call f() is an lvalue expression. ] ]

            [注意:某些內置運算符以及一些函數調用會返回左值。[例1:如果 E 是一個指針類型的表達式,那么 *E 是一個左值表達式,指示指針 E 所指向的那個對象或者函數。例2:函數
            int& f();
            返回左值,所以函數調用 f() 是一個左值表達式。] ]

            4 [Note: some built-in operators expect lvalue operands. [Example: built-in assignment operators all expect their left hand operands to be lvalues. ] Other built-in operators yield rvalues, and some expect them. [Example: the unary and binary + operators expect rvalue arguments and yield rvalue results. ] The discussion of each built-in operator in clause 5 indicates whether it expects lvalue operands and whether it yields an lvalue. ]

            [注意:某些內置運算符需要左值操作數。[例:所有內置的賦值運算符的左操作數都必須是左值。] 有些內置運算符會返回右值結果,有些會需要右值操作數。[例:一元運算符“+”和二元運算符“+”都需要右值操作數,并且返回右值結果。] 我們在條款 5 中會對所有內置運算符進行討論,指出它們的操作數和返回結果是左值還是右值。]

            5 The result of calling a function that does not return a reference is an rvalue. User defined operators are functions, and whether such operators expect or yield lvalues is determined by their parameter and return
            types.

            調用返回值為非引用類型的函數,結果是右值。用戶自定義的運算符也是函數,這些運算符的操作數以及結果是左值還是右值,取決于(運算符重載)函數的參數和返回值類型。

            6 An expression which holds a temporary object resulting from a cast to a nonreference type is an rvalue (this includes the explicit creation of an object using functional notation (5.2.3)).

            對非引用類型的轉換表達式(包括使用函數式的記號進行顯示創建)是右值,它將返回一個臨時對象。


            __________________
            47) Expressions such as invocations of constructors and of functions that return a class type refer to objects, and the implementation can invoke a member function upon such objects, but the expressions are not lvalues.

            有些表達式,比如調用構造函數的表達式,以及調用返回類類型的函數的表達式,它們也是對象,且可以對它們調用成員函數,但這種表達式不是左值。

            ____________________________________華麗的分頁符____________________________________

             

            7 Whenever an lvalue appears in a context where an rvalue is expected, the lvalue is converted to an rvalue; see 4.1, 4.2, and 4.3.

            如果在一個需要右值的場合出現了左值,這個左值將被轉換成右值。
            見 4.1、4.2、4.3。

            8 The discussion of reference initialization in 8.5.3 and of temporaries in 12.2 indicates the behavior of lvalues and rvalues in other significant contexts.

            12.2 中關于引用的初始化和關于臨時對象的討論,也指出了左右值在其他重要場合的行為。

            9 Class rvalues can have cv-qualified types; non-class rvalues always have cv-unqualified types. Rvalues shall always have complete types or the void type; in addition to these types, lvalues can also have incomplete types.

            類類型的右值可以具有 cv 限定符;非類類型的右值不能被 cv 限定符修飾。右值通常是完整類型或者 void 類型,而對于左值來說,除了完整類型和 void 類型外,還可以是不完整類型。

            10 An lvalue for an object is necessary in order to modify the object except that an rvalue of class type can also be used to modify its referent under certain circumstances. [Example: a member function called for an object (9.3) can modify the object. ]

            通常情況下,如果要修改一個對象,它必須是左值。但在某些特定的場合,右值形式的類對象也可以被修改。[例:調用一個對象的成員函數(9.3),可以修改對象本身。]

            11 Functions cannot be modified, but pointers to functions can be modifiable.

            函數(對象)不能(在運行時)被修改,但是函數指針可以。

            12 A pointer to an incomplete type can be modifiable. At some point in the program when the pointed to type is complete, the object at which the pointer points can also be modified.

            指向一個不完整類型的指針可能是可修改的。當這個被指向的類型某時某刻成為完整類型后,這個指針所指向的那個對象也是可修改的。

            13 The referent of a const-qualified expression shall not be modified (through that expression), except that if it is of class type and has a mutable component, that component can be modified (7.1.5.1).

            被 const 限定的表達式所對應的對象不能(通過該表達式)被修改;除非這個對象是類類型并且含有 mutable 成員,此時該 mutable 成員可以被修改。

            14 If an expression can be used to modify the object to which it refers, the expression is called modifiable. A program that attempts to modify an object through a nonmodifiable lvalue or rvalue expression is illformed.

            如果一個表達式可以被用來修改此表達式對應的對象,那么這個表達式被稱為可修改的。企圖通過一個不可修改的左值者右值表達式去修改一個對象,是非法的。

            15 If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined 48):
            — the dynamic type of the object,
            — a cv-qualified version of the dynamic type of the object,
            — a type that is the signed or unsigned type corresponding to the dynamic type of the object,
            — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of
            the object,
            — an aggregate or union type that includes one of the aforementioned types among its members (including,
            recursively, a member of a subaggregate or contained union),
            — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
            — a char or unsigned char type.

            如果程序通過下列類型之外類型的左值訪問一個對象的值,其行為是未定義的:

            ——對象的動態類型;
            ——CV 限定的對象動態類型;
            ——對象的動態類型對應的有符號或無符號類型;
            ——CV 限定的對象動態類型有符號或無符號類型;
            ——一個成員中含有聚合或者聯合類型的聚合或者聯合類型(包括遞歸形式的定義以及成員中有子聚合類型或者包含一個聯合)
            ——對象的動態類型的基類類型(可以被 cv 限定符修飾)
            ——char 或 unsigned char 類型


            __________________
            48) The intent of this list is to specify those circumstances in which an object may or may not be aliased.
            給出這份列表的目的是指明一些特定情形,在這些情形下對象可能被重疊,但也有可能不是,我們無法預知。

            ____________________________________華麗的分隔符____________________________________

             

            以上,求指正,包括理解誤區和語言組織不合理的,歡迎指出~ ^_^

            posted @ 2012-02-29 22:50 溪流 閱讀(1575) | 評論 (0)編輯 收藏

            如題,大致看了下網上能找到的一些規范,覺得大體有這么三個方面吧,一個是排版方面的,一個是命名方面的,一個是書寫邏輯方面的。

            排版方面的大概有,如何縮進,如何使用空格、換行,等等。命名方面的包括變量、函數、類、文件的取名等等。書寫邏輯方面的就比較多了,可能包括:
            是否全面使用異常、出錯處理資源清理如何組織、如何利用編譯提示防止常見錯誤……

            一時間列不全。網上常見的文檔我會參考的。除此之外,想從大家這里征求下,以上幾個大方面之外,還有沒有比較重要的方面?大家日常工作中有沒有遇到一些特別希望別人也使用和自己一樣的方式做的事?以及,哪些規定比較容易被推動?哪些規定不容易被推動?如果有一個規則強加在你頭上,你會有怎樣的心理?等等……

            如果您有想法,請回復下,我們討論討論^_^

            ----------

            順便再問個問題,Windows 上的開發,大家喜歡動態鏈接 CRT(/MD、/MDd) 還是靜態鏈接 CRT(/MT、/MTd)?為什么?個人傾向于哪種?在公司里又是怎樣做的?

            posted @ 2011-07-12 22:22 溪流 閱讀(2105) | 評論 (17)編輯 收藏

            如題。

            稍微解釋下,因為有可能有人會誤會:放新線程里面去不就可以了?這沒有解決問題。如此的話,你那個線程函數怎么寫?或者線程函數里調用的某個任務函數怎么寫?總之,多線程雖然總是出現在這些問題的解決方案中,但不是多線程解決了這個問題。嗯……不知道說清楚了沒?

            目前我心里的答案只有這一種模式:

            bool DoTask(HANDLE hQuitSignal)
            {
                while (!QuitCondition)
                {
                    if (WaitForSingleObject(hQuitSignal, 0) == WAIT_OBJECT_0)
                    {
                        return false;
                    }

                    // Do something
                }

                return true;
            }

            其中,“// Do something”部分要細化到瞬間執行完成的細度。

            但是我很困惑的是,如果這些任務很繁重,難道我必須每進行一些操作就 if (WaitForSingleObject(hQuitSignal, 0) == WAIT_OBJECT_0) 檢查下嗎?這樣豈不是這種檢測代碼充斥在任務中了?

            不知各位有何經驗和體會,求教~

            posted @ 2011-05-26 00:36 溪流 閱讀(2900) | 評論 (29)編輯 收藏

            標題中說的 Tuple 是指類似 boost::tuple 這樣的設施。

            很多時候我們需要返回/傳入一堆參數,所以不得不每次定義一些為了數據傳輸的結構。Tuple 就是用來解決這一問題的,它提供即時構造一個這樣的結構體的功能。而所付出的代價是,喪失各個成員的明確含義,只留下成員的序號。

            兩個元素的 Tuple 就是 Pair,如 std::pair。下面我們來建立針對有限個元素的 Tuple。對于一個元素、兩個元素、三個元素,我們可以分別如下實現:

            template <typename T0>
            struct Tuple
            {
                T0 _0;
            };

            template <typename T0, typename T1>
            struct Tuple
            {
                T0 _1;
                T1 _1;
            };

            template <typename T0, typename T1, typename T2>
            struct Tuple
            {
                T0 _1;
                T1 _1;
                T2 _2;
            };

            但是這三個寫在一起,就會出錯。為此,我們可以先定義一個含足夠多模版參數的 Tuple,然后上面三個分別作為偏特化版本:

            template <typename T0 = NullType, typename T1= NullType, typename T2= NullType, typename T3= NullType, typename T4= NullType>
            struct Tuple;

            template <typename T0>
            struct Tuple<T0>
            {
                T0 _0;
            };

            template <typename T0, typename T1>
            struct Tuple<T0, T1>
            {
                T0 _1;
                T1 _1;
            };

            template <typename T0, typename T1, typename T2>
            struct Tuple<T0, T1, T2>
            {
                T0 _1;
                T1 _1;
                T2 _2;
            };

            如果手寫的話,這也可以。如果不手寫,我們可以繼續用之前《C++ 下 Function 對象的實現(下)》中的宏循環方案。此方案的一個正式版本見 xlMacros.h

            定義帶默認值 NullType 的模版參數聲明序列如下:

            #define XL_TUPLE_TYPENAME_DECLARE_NT_PATTERN(n)     typename T##n = NullType
            #define XL_TUPLE_TYPENAME_DECLARE_NT(n)             XL_REPZ(XL_TUPLE_TYPENAME_DECLARE_NT_PATTERN, n, XL_COMMA)

            它將被展開為: typename T0 = NullType, typename T1 = NullType, typename T2 = NullType, …, typename Tn = NullType

            定義不帶默認值的模版參數聲明序列如下:

            #define XL_TUPLE_TYPENAME_DECLARE_PATTERN(n)        typename T##n
            #define XL_TUPLE_TYPENAME_DECLARE(n)                XL_REPZ(XL_TUPLE_TYPENAME_DECLARE_PATTERN, n, XL_COMMA)

            它將被展開為:typename T0, typename T1, typename T2, …, typename Tn

            定義模版參數使用序列如下:

            #define XL_TUPLE_TYPENAME_LIST_PATTERN(n)           T##n
            #define XL_TUPLE_TYPENAME_LIST(n)                   XL_REPZ(XL_TUPLE_TYPENAME_LIST_PATTERN, n, XL_COMMA)

            它將被展開為 T0, T1, T2, …, Tn

            定義成員變量聲明序列如下:

            #define XL_TUPLE_MEMBER_DECLARE_PATTERN(n)          T##n _##n;
            #define XL_TUPLE_MEMBER_DECLARE(n)                  XL_REPZ(XL_TUPLE_MEMBER_DECLARE_PATTERN, n, XL_NIL)

            它將被展開為:T0 _0; T1 _1; T2 _2; … Tn _n;

            現在我們開始組裝:

            #ifndef XL_TUPLE_DEFINE_MAX
            #define XL_TUPLE_DEFINE_MAX  20
            #endif

            template <XL_TUPLE_TYPENAME_DECLARE_NT(XL_INC(XL_TUPLE_DEFINE_MAX))>
            struct Tuple;

            template <XL_TUPLE_TYPENAME_DECLARE(n)>
            struct Tuple<XL_TUPLE_TYPENAME_LIST(n)>
            {
                XL_TUPLE_MEMBER_DECLARE(n)
            };

            其中后一個還帶有宏參數 n。我們將這整一個定義成宏,然后進行宏循環:

            #define XL_TUPLE_IMPLEMENT_PATTERN(n)   \
                                                    \
            template <XL_TUPLE_TYPENAME_DECLARE(n)> \
            struct Tuple<XL_TUPLE_TYPENAME_LIST(n)> \
            {                                       \
                XL_TUPLE_MEMBER_DECLARE(n)          \
            };                                      \

            #define XL_TUPLE_IMPLEMENT(n)    XL_REPY(XL_TUPLE_IMPLEMENT_PATTERN, n, XL_NIL)

            之后再使用這個宏:

            XL_TUPLE_IMPLEMENT(XL_TUPLE_DEFINE_MAX)

            到此為止,上文一開始提出的 Tuple 已經實現,并支持到最大約 20 個元素左右。

            然后我們可以考慮增加各種方便使用的功能。

            1. 默認構造函數。
            2. 帶有 n 個參數的構造函數。相關宏定義:
              #define XL_TUPLE_INITIALIZE_LIST_PATTERN(n)         _##n(_##n)
              #define XL_TUPLE_INITIALIZE_LIST(n)                 XL_REPZ(XL_TUPLE_INITIALIZE_LIST_PATTERN, n, XL_COMMA)
            3. 拷貝構造函數。相關宏定義:
              #define XL_TUPLE_INITIALIZE_LIST_COPY_PATTERN(n)    _##n(that._##n)
              #define XL_TUPLE_INITIALIZE_LIST_COPY(n)            XL_REPZ(XL_TUPLE_INITIALIZE_LIST_COPY_PATTERN, n, XL_COMMA)
            4. 賦值函數:
              #define XL_TUPLE_ASSIGN_PATTERN(n)                  this->_##n = that._##n;
              #define XL_TUPLE_ASSIGN(n)                          XL_REPZ(XL_TUPLE_ASSIGN_PATTERN, n, XL_NIL)
            5. 各種比較函數。請注意對各元素的相應比較運算符的依賴。這里定義成,Tuple 的 < 只依賴于各元素的 <,Tuple 的 != 也只依賴于各元素的 !=,如此類推。

              #define XL_TUPLE_EQUAL_PATTERN(n)                   this->_##n == that._##n
              #define XL_TUPLE_EQUAL(n)                           XL_REPZ(XL_TUPLE_EQUAL_PATTERN, n, &&)
            6. #define XL_TUPLE_NOT_EQUAL_PATTERN(n)               this->_##n != that._##n
              #define XL_TUPLE_NOT_EQUAL(n)                       XL_REPZ(XL_TUPLE_NOT_EQUAL_PATTERN, n, ||)

              #define XL_TUPLE_LITTER_PATTERN(n)                  if (this->_##n < that._##n)         \
                                                                  {                                   \
                                                                      return true;                    \
                                                                  }                                   \
                                                                  else if (that._##n < this->_##n)    \
                                                                  {                                   \
                                                                      return false;                   \
                                                                  }
              #define XL_TUPLE_LITTER(n)                          XL_REPZ(XL_TUPLE_LITTER_PATTERN, n, XL_NIL)

              #define XL_TUPLE_GREATER_PATTERN(n)                 if (this->_##n > that._##n)         \
                                                                  {                                   \
                                                                      return true;                    \
                                                                  }                                   \
                                                                  else if (that._##n > this->_##n)    \
                                                                  {                                   \
                                                                      return false;                   \
                                                                  }
              #define XL_TUPLE_GREATER(n)                         XL_REPZ(XL_TUPLE_GREATER_PATTERN, n, XL_NIL)

            同時 Tuple 中也增加相應的函數,即可。

            最終代碼見 xlTuple.h,這里不貼了。

            請多多指正。

            posted @ 2011-04-28 22:05 溪流 閱讀(2400) | 評論 (8)編輯 收藏

            有個需求,能否做到實現一個類似這樣的函數:

            template <typename T1, typename T2>
            XXX Min(T1 t1, T2 t2)
            {
                return (t1 < t2 ? t1 : t2);
            }

            其中 XXX 是我們要推導出的類型。

            以下是一個失敗的嘗試。

            我記得 Loki 里有關于如何判斷某個類型能否隱式轉換為另一個類型的東西,大意如下:

            template <typename T, typename U>
            class Conversion
            {
            private:
                typedef char Small;
                class Big { char XXX[2]; };
                static Small Test(U);
                static Big Test(...);
                static T MakeT();
            public:
                enum
                {
                    Exists = (sizeof(Test(MakeT())) == sizeof(Small)),
                };
            };

            如此,Conversion<T, U>::Exists 就能判斷 T 到 U 的轉換是否存在了。

            然后再搞個選擇:

            template <bool Condition, typename TypeIfTrue, typename TypeIfFalse>
            struct Select
            {
                typedef TypeIfFalse Type;
            };

            template <typename TypeIfTrue, typename TypeIfFalse>
            struct Select<true, TypeIfTrue, TypeIfFalse>
            {
                typedef TypeIfTrue Type;
            };

            最后,再來個:

            struct NullType;

            template <typename T, typename U>
            struct CommonType
            {
                typedef typename Select<Conversion<T, U>::exists,
                                                    U,
                                                    typename Select<Conversion<U, T>::exists,
                                                                            T,
                                                                            NullType>::Type
                                                   >::Type Type;
            };

            那么 CommonType<T1, T2> 就是 T1 和 T2 之間哪個是他們的共有類型了。

            測試:

            int main()
            {
                CommonType<int, double>::Type m = 0;

                return 0;
            }

            調試,確認 m 是 double 的。但是反過來寫 CommonType<double, int>::Type m = 0;,m 卻是 int 的。

            這說明這套機制一開始就有問題,Test(U) 和 Test(…) 兩個重載函數中,Test(…) 不會在需要 double 轉 int 時勝出。這是第一個問題。

            第二個問題,當寫下如下代碼的時候:

            template <typename T1, typename T2>
            CommonType<T1, T2>::Type Min(T1 t1, T2 t2)
            {
                return (t1 < t2 ? t1 : t2);
            }

            編譯無法通過。原因是返回類型中的 CommonType 中的模板參數 T、U 無法接受此時還不能確定的 T1、T2。

            (更正:不是這個原因,返回類型前加 typename 即可。現在問題還是第一個問題。)

            請教各位,有沒有什么方法做到?歡迎指教~

            C++ 0x 中就能很方便做到了:

            template <typename T1, typename T2>
            auto Min(T1 t1, T2 t2) -> decltype(t1 + t2)
            {
                return (t1 < t2 ? t1 : t2);
            }

            int main()
            {
                int a = 2;
                double b = 1.0;
                auto m = Min(a, b);

                return 0;
            }

            posted @ 2011-03-29 21:27 溪流 閱讀(1896) | 評論 (16)編輯 收藏
            僅列出標題
            共18頁: First 4 5 6 7 8 9 10 11 12 Last 
            日本精品久久久久中文字幕| 亚洲精品国产美女久久久| 99久久精品国产一区二区| 久久久久亚洲精品天堂久久久久久 | 亚洲欧美成人综合久久久| 亚洲精品成人网久久久久久| 久久丝袜精品中文字幕| 久久伊人影视| 亚洲欧美日韩久久精品第一区| 久久久久波多野结衣高潮| 一本色道久久99一综合| 人妻无码久久一区二区三区免费| 久久久久久人妻无码| 国产产无码乱码精品久久鸭| 亚洲国产精品热久久| 久久午夜无码鲁丝片午夜精品| 久久青青色综合| 久久99精品国产麻豆| 丁香五月综合久久激情| 午夜视频久久久久一区| 亚洲精品国产美女久久久| 久久久久久a亚洲欧洲aⅴ| 久久久久亚洲AV成人网| 99精品国产99久久久久久97| 久久精品午夜一区二区福利| 久久久久久久尹人综合网亚洲| 亚洲欧洲久久av| 久久国产精品成人片免费| 久久久中文字幕日本| 久久国产欧美日韩精品| 欧美午夜精品久久久久久浪潮| 热re99久久6国产精品免费| 国产激情久久久久影院老熟女免费 | 久久夜色精品国产噜噜亚洲a | 久久人人爽人人爽人人av东京热 | 久久99精品久久久大学生| 国产Av激情久久无码天堂| 亚洲欧美日韩精品久久亚洲区 | 久久亚洲AV成人出白浆无码国产| 国产精品免费久久久久久久久| 久久亚洲精品成人无码网站|