最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?const與constexpr區(qū)別小結(jié)

 更新時(shí)間:2024年03月08日 15:41:12   作者:程序員老舅  
C++11標(biāo)準(zhǔn)中,const用于為修飾的變量添加只讀屬性,而constexpr關(guān)鍵字則用于指明其后是一個(gè)常量,本文主要介紹了C++?const與constexpr區(qū)別小結(jié),感興趣的可以了解一下

C++ 11標(biāo)準(zhǔn)中,const 用于為修飾的變量添加“只讀”屬性而 constexpr關(guān)鍵字則用于指明其后是一個(gè)常量,編譯器在編譯程序時(shí)可以順帶將其結(jié)果計(jì)算出來,而無需等到程序運(yùn)行階段,這樣的優(yōu)化極大地提高了程序的執(zhí)行效率,本文重點(diǎn)介紹C++ const與constexpr區(qū)別介紹,一起看看吧。

constexpr:常量表達(dá)式

所謂常量表達(dá)式,指的就是由多個(gè)(≥1)常量組成的表達(dá)式。換句話說,如果表達(dá)式中的成員都是常量,那么該表達(dá)式就是一個(gè)常量表達(dá)式。這也意味著,常量表達(dá)式一旦確定,其值將無法修改。

實(shí)際開發(fā)中,我們經(jīng)常會(huì)用到常量表達(dá)式。以定義數(shù)組為例,數(shù)組的長(zhǎng)度就必須是一個(gè)常量表達(dá)式

// 1)
int url[10];//正確
// 2)
int url[6 + 4];//正確
// 3)
int length = 6;
int url[length];//錯(cuò)誤,length是變量

上述代碼演示了 3 種定義 url 數(shù)組的方式,其中第 1、2 種定義 url 數(shù)組時(shí),長(zhǎng)度分別為 10 和 6+4,顯然它們都是常量表達(dá)式,可以用于表示數(shù)組的長(zhǎng)度;第 3 種 url 數(shù)組的長(zhǎng)度為 length,它是變量而非常量,因此不是一個(gè)常量表達(dá)式,無法用于表示數(shù)組的長(zhǎng)度。

常量表達(dá)式的應(yīng)用場(chǎng)景還有很多,比如匿名枚舉、switch-case 結(jié)構(gòu)中的 case 表達(dá)式等,感興趣的讀者可自行編碼測(cè)試,這里不再過多舉例。

我們知道,C++ 程序的執(zhí)行過程大致要經(jīng)歷編譯、鏈接、運(yùn)行這 3 個(gè)階段。值得一提的是,常量表達(dá)式和非常量表達(dá)式的計(jì)算時(shí)機(jī)不同,非常量表達(dá)式只能在程序運(yùn)行階段計(jì)算出結(jié)果;而常量表達(dá)式的計(jì)算往往發(fā)生在程序的編譯階段,這可以極大提高程序的執(zhí)行效率,因?yàn)楸磉_(dá)式只需要在編譯階段計(jì)算一次,節(jié)省了每次程序運(yùn)行時(shí)都需要計(jì)算一次的時(shí)間。

對(duì)于用 C++ 編寫的程序,性能往往是永恒的追求。那么在實(shí)際開發(fā)中,如何才能判定一個(gè)表達(dá)式是否為常量表達(dá)式,進(jìn)而獲得在編譯階段即可執(zhí)行的“特權(quán)”呢?除了人為判定外,C++11 標(biāo)準(zhǔn)還提供有 constexpr 關(guān)鍵字。

constexpr 關(guān)鍵字的功能是使指定的常量表達(dá)式獲得在程序編譯階段計(jì)算出結(jié)果的能力,而不必等到程序運(yùn)行階段。C++ 11 標(biāo)準(zhǔn)中,constexpr 可用于修飾普通變量、函數(shù)(包括模板函數(shù))以及類的構(gòu)造函數(shù)。

注意:獲得在編譯階段計(jì)算出結(jié)果的能力,并不代表 constexpr修飾的表達(dá)式一定會(huì)在程序編譯階段被執(zhí)行,具體的計(jì)算時(shí)機(jī)還是編譯器說了算。

constexpr修飾普通變量

C++11 標(biāo)準(zhǔn)中,定義變量時(shí)可以用constexpr 修飾,從而使該變量獲得在編譯階段即可計(jì)算出結(jié)果的能力。

注意:使用 constexpr 修改普通變量時(shí),變量必須經(jīng)過初始化且初始值必須是一個(gè)常量表達(dá)式。舉個(gè)例子:

#include <iostream>
using namespace std;
int main()
{
    constexpr int num = 1 + 2 + 3;
    int url[num] = {1,2,3,4,5,6};
    couts<< url[1] << endl;
    return 0;
}

程序執(zhí)行結(jié)果為:2

讀者可嘗試將 constexpr 刪除,此時(shí)編譯器會(huì)提示“url[num] 定義中 num 不可用作常量”。

可以看到,程序第 6 行使用 constexpr 修飾 num 變量,同時(shí)將 “1+2+3” 這個(gè)常量表達(dá)式賦值給 num。由此,編譯器就可以在編譯時(shí)期對(duì) num 這個(gè)表達(dá)式進(jìn)行計(jì)算,因?yàn)?num 可以作為定義數(shù)組時(shí)的長(zhǎng)度。

有讀者可能發(fā)現(xiàn),將此示例程序中的 constexpr 用const關(guān)鍵字替換也可以正常執(zhí)行,這是因?yàn)?num 的定義同時(shí)滿足“num 是 const 常量且使用常量表達(dá)式為其初始化”這 2 個(gè)條件,由此編譯器會(huì)認(rèn)定 num 是一個(gè)常量表達(dá)式。

另外需要重點(diǎn)提出的是,當(dāng)常量表達(dá)式中包含浮點(diǎn)數(shù)時(shí),考慮到程序編譯和運(yùn)行所在的系統(tǒng)環(huán)境可能不同,常量表達(dá)式在編譯階段和運(yùn)行階段計(jì)算出的結(jié)果精度很可能會(huì)受到影響,因此 C++11 標(biāo)準(zhǔn)規(guī)定,浮點(diǎn)常量表達(dá)式在編譯階段計(jì)算的精度要至少等于(或者高于)運(yùn)行階段計(jì)算出的精度。

constexpr修飾函數(shù)

constexpr 還可以用于修飾函數(shù)的返回值,這樣的函數(shù)又稱為“常量表達(dá)式函數(shù)”。

注意,constexpr 并非可以修改任意函數(shù)的返回值。換句話說,一個(gè)函數(shù)要想成為常量表達(dá)式函數(shù),必須滿足如下 4 個(gè)條件:1) 該函數(shù)必須有返回值,即函數(shù)的返回值類型不能是 void。
舉個(gè)例子:

constexpr void display() {
    //函數(shù)體
}

像上面這樣定義的返回值類型為 void 的函數(shù),不屬于常量表達(dá)式函數(shù)。原因很簡(jiǎn)單,因?yàn)橥ㄟ^類似的函數(shù)根本無法獲得一個(gè)常量。
2) 整個(gè)函數(shù)的函數(shù)體中,除了可以包含 using 指令、typedef 語句以及 static_assert 斷言外,只能包含一條 return 返回語句。
舉個(gè)例子:

constexpr int display(int x) {
   int ret = 1 + 2 + x;
   return ret;
}

注意,這個(gè)函數(shù)是無法通過編譯的,因?yàn)樵摵瘮?shù)的返回值用 constexpr 修飾,但函數(shù)內(nèi)部包含多條語句。如下是正確的定義 display() 常量表達(dá)式函數(shù)的寫法:

constexpr int display(int x) {
    //可以添加 using 執(zhí)行、typedef 語句以及 static_assert 斷言
    return 1 + 2 + x;
}

可以看到,display() 函數(shù)的返回值是用 constexpr 修飾的 int 類型值,且該函數(shù)的函數(shù)體中只包含一個(gè)return語句。
3)return 返回的表達(dá)式必須是常量表達(dá)式
舉個(gè)例子:

#include <iostream>
using namespace std;
int num = 3;
constexpr int display(int x){
    return num + x;
}
int main()
{
    //調(diào)用常量表達(dá)式函數(shù)
    int a[display(3)] = { 1,2,3,4 };
    return 0;
}

該程序無法通過編譯,編譯器報(bào)“display(3) 的結(jié)果不是常量”的異常。

常量表達(dá)式函數(shù)的返回值必須是常量表達(dá)式的原因很簡(jiǎn)單,如果想在程序編譯階段獲得某個(gè)函數(shù)返回的常量,則該函數(shù)的 return 語句中就不能包含程序運(yùn)行階段才能確定值的變量。

注意,在常量表達(dá)式函數(shù)的 return 語句中,不能包含賦值的操作(例如 return x=1 在常量表達(dá)式函數(shù)中不允許的)。另外,用 constexpr 修改函數(shù)時(shí),函數(shù)本身也是支持遞歸的,感興趣的讀者可自行嘗試編碼測(cè)試。

4) 函數(shù)在使用之前,必須有對(duì)應(yīng)的定義語句。我們知道,函數(shù)的使用分為“聲明”和“定義”兩部分,普通的函數(shù)調(diào)用只需要提前寫好該函數(shù)的聲明部分即可(函數(shù)的定義部分可以放在調(diào)用位置之后甚至其它文件中),但常量表達(dá)式函數(shù)在使用前,必須要有該函數(shù)的定義。舉個(gè)例子:

#include <iostream>
using namespace std;
//普通函數(shù)的聲明
int noconst_dis(int x);
//常量表達(dá)式函數(shù)的聲明
constexpr int display(int x);
//常量表達(dá)式函數(shù)的定義
constexpr int display(int x){
    return 1 + 2 + x;
}
int main()
{
    //調(diào)用常量表達(dá)式函數(shù)
    int a[display(3)] = { 1,2,3,4 };
    cout << a[2] << endl;
    //調(diào)用普通函數(shù)
    cout << noconst_dis(3) << endl;
    return 0;
}
//普通函數(shù)的定義
int noconst_dis(int x) {
    return 1 + 2 + x;
}

程序執(zhí)行結(jié)果為:

3
6

讀者可自行將 display() 常量表達(dá)式函數(shù)的定義調(diào)整到 main() 函數(shù)之后,查看編譯器的報(bào)錯(cuò)信息??梢钥吹剑?strong>普通函數(shù)在調(diào)用時(shí),只需要保證調(diào)用位置之前有相應(yīng)的聲明即可;而常量表達(dá)式函數(shù)則不同,調(diào)用位置之前必須要有該函數(shù)的定義,否則會(huì)導(dǎo)致程序編譯失敗。

constexpr修飾類的構(gòu)造函數(shù)

對(duì)于 C++ 內(nèi)置類型的數(shù)據(jù),可以直接用 constexpr 修飾,但如果是自定義的數(shù)據(jù)類型(用 struct 或者 class 實(shí)現(xiàn)),直接用 constexpr 修飾是不行的

舉個(gè)例子:

#include <iostream>
using namespace std;
//自定義類型的定義
constexpr struct myType {
    const char* name;
    int age;
    //其它結(jié)構(gòu)體成員
};
int main()
{
    constexpr struct myType mt{ "zhangsan", 10 };
    cout << mt.name << " " << mt.age << endl;
    return 0;
}

此程序是無法通過編譯的,編譯器會(huì)拋出“constexpr不能修飾自定義類型”的異常。

當(dāng)我們想自定義一個(gè)可產(chǎn)生常量的類型時(shí),正確的做法是在該類型的內(nèi)部添加一個(gè)常量構(gòu)造函數(shù)。例如,修改上面的錯(cuò)誤示例如下:

#include <iostream>
using namespace std;
//自定義類型的定義
struct myType {
    constexpr myType(char *name,int age):name(name),age(age){};
    const char* name;
    int age;
    //其它結(jié)構(gòu)體成員
};
int main()
{
    constexpr struct myType mt { "zhangsan", 10 };
    cout << mt.name << " " << mt.age << endl;
    return 0;
}

程序執(zhí)行結(jié)果為:

zhangsan 10

可以看到,在 myType 結(jié)構(gòu)體中自定義有一個(gè)構(gòu)造函數(shù),借助此函數(shù),用 constexpr 修飾的 myType 類型的mt常量即可通過編譯。

注意,constexpr 修飾類的構(gòu)造函數(shù)時(shí),要求該構(gòu)造函數(shù)的函數(shù)體必須為空,且采用初始化列表的方式為各個(gè)成員賦值時(shí),必須使用常量表達(dá)式。

前面提到,constexpr 可用于修飾函數(shù),而類中的成員方法完全可以看做是“位于類這個(gè)命名空間中的函數(shù)”,所以 constexpr 也可以修飾類中的成員函數(shù),只不過此函數(shù)必須滿足前面提到的 4 個(gè)條件。

舉個(gè)例子:

#include <iostream>
using namespace std;
//自定義類型的定義
class myType {
public:
    constexpr myType(const char *name,int age):name(name),age(age){};
    constexpr const char * getname(){
        return name;
    }
    constexpr int getage(){
        return age;
    }
private:
    const char* name;
    int age;
    //其它結(jié)構(gòu)體成員
};
int main()
{
    constexpr struct myType mt { "zhangsan", 10 };
    constexpr const char * name = mt.getname();
    constexpr int age = mt.getage();
    cout << name << " " << age << endl;
    return 0;
}

程序執(zhí)行結(jié)果為:

zhangsan 10

注意,C++11 標(biāo)準(zhǔn)中,不支持用 constexpr 修飾帶有 virtual 的成員方法。

constexpr修飾模板函數(shù)

C++11 語法中,constexpr 可以修飾模板函數(shù),但由于模板中類型的不確定性,因此模板函數(shù)實(shí)例化后的函數(shù)是否符合常量表達(dá)式函數(shù)的要求也是不確定的。

針對(duì)這種情況下,C++11 標(biāo)準(zhǔn)規(guī)定,如果 constexpr 修飾的模板函數(shù)實(shí)例化結(jié)果不滿足常量表達(dá)式函數(shù)的要求,則 constexpr 會(huì)被自動(dòng)忽略,即該函數(shù)就等同于一個(gè)普通函數(shù)。

舉個(gè)例子:

#include <iostream>
using namespace std;
//自定義類型的定義
struct myType {
    const char* name;
    int age;
    //其它結(jié)構(gòu)體成員
};
//模板函數(shù)
template<typename T>
constexpr T dispaly(T t){
    return t;
}
int main()
{
    struct myType stu{"zhangsan",10};
    //普通函數(shù)
    struct myType ret = dispaly(stu);
    cout << ret.name << " " << ret.age << endl;
    //常量表達(dá)式函數(shù)
    constexpr int ret1 = dispaly(10);
    cout << ret1 << endl;
    return 0;
}

程序執(zhí)行結(jié)果為:

zhangsan 10
10

可以看到,示例程序中定義了一個(gè)模板函數(shù) display(),但由于其返回值類型未定,因此在實(shí)例化之前無法判斷其是否符合常量表達(dá)式函數(shù)的要求.

const與constexpr區(qū)別:

一些讀者在學(xué)習(xí)過程中,經(jīng)常會(huì)把 const 和 constexpr 搞混,不知道什么時(shí)候用 const,什么時(shí)候用 constexpr。本節(jié)就帶領(lǐng)大家對(duì) const 和 constexpr 做系統(tǒng)地區(qū)分。

有關(guān) constexpr 的功能和用法,您可以閱讀《C++11 constexpr》一節(jié)。

我們知道,constexpr 是 C++ 11 標(biāo)準(zhǔn)新添加的關(guān)鍵字,在此之前(C++ 98/03標(biāo)準(zhǔn))只有const關(guān)鍵字,其在實(shí)際使用中經(jīng)常會(huì)表現(xiàn)出兩種不同的語義。舉個(gè)例子:

#include <iostream>
#include <array>
using namespace std;
void dis_1(const int x){
    //錯(cuò)誤,x是只讀的變量
    array <int,x> myarr{1,2,3,4,5};
    cout << myarr[1] << endl;
}
void dis_2(){
    const int x = 5;
    array <int,x> myarr{1,2,3,4,5};
    cout << myarr[1] << endl;
}
int main()
{
   dis_1(5);
   dis_2();
}

可以看到,dis_1() 和 dis_2() 函數(shù)中都包含一個(gè) const int x,但 dis_1() 函數(shù)中的 x 無法完成初始化 array 容器的任務(wù),而 dis_2() 函數(shù)中的 x 卻可以。

這是因?yàn)?,dis_1() 函數(shù)中的“const int x”只是想強(qiáng)調(diào) x 是一個(gè)只讀的變量,其本質(zhì)仍為變量,無法用來初始化 array 容器;而 dis_2() 函數(shù)中的“const int x”,表明 x 是一個(gè)只讀變量的同時(shí),x 還是一個(gè)值為 5 的常量,所以可以用來初始化array容器。

C++ 11標(biāo)準(zhǔn)中,為了解決const關(guān)鍵字的雙重語義問題,保留了const表示“只讀”的語義,而將“常量”的語義劃分給了新添加的 constexpr 關(guān)鍵字。因此 C++11 標(biāo)準(zhǔn)中,建議將const和 constexpr 的功能區(qū)分開,即凡是表達(dá)“只讀”語義的場(chǎng)景都使用 const,表達(dá)“常量”語義的場(chǎng)景都使用 constexpr。

在上面的實(shí)例程序中,dis_2() 函數(shù)中使用 const int x 是不規(guī)范的,應(yīng)使用 constexpr 關(guān)鍵字。

有讀者可能會(huì)問,“只讀”不就意味著其不能被修改嗎?答案是否定的,“只讀”和“不允許被修改”之間并沒有必然的聯(lián)系,舉個(gè)例子:

#include <iostream>
using namespace std;
int main()
{
    int a = 10;
    const int & con_b = a;
    cout << con_b << endl;
    a = 20;
    cout << con_b << endl;
}

程序執(zhí)行結(jié)果為:

10
20

可以看到,程序中用 const 修飾了 con_b 變量,表示該變量“只讀”,即無法通過變量自身去修改自己的值。但這并不意味著 con_b 的值不能借助其它變量間接改變,通過改變 a 的值就可以使con_b的值發(fā)生變化。
在大部分實(shí)際場(chǎng)景中,const 和 constexpr 是可以混用的,例如:

const int a = 5 + 4;
constexpr int a = 5 + 4;

它們是完全等價(jià)的,都可以在程序的編譯階段計(jì)算出結(jié)果。但在某些場(chǎng)景中,必須明確使用 constexpr,例如:

#include <iostream>
#include <array>
using namespace std;
constexpr int sqr1(int arg){
    return arg*arg;
}
const int sqr2(int arg){
    return arg*arg;
}
int main()
{
    array<int,sqr1(10)> mylist1;//可以,因?yàn)閟qr1時(shí)constexpr函數(shù)
    array<int,sqr2(10)> mylist1;//不可以,因?yàn)閟qr2不是constexpr函數(shù)
    return 0;
}

其中,因?yàn)?sqr2() 函數(shù)的返回值僅有const修飾,而沒有用更明確的 constexpr 修飾,導(dǎo)致其無法用于初始化 array 容器(只有常量才能初始化array容器)。

總的來說在 C++ 11 標(biāo)準(zhǔn)中,const 用于為修飾的變量添加“只讀”屬性;而 constexpr 關(guān)鍵字則用于指明其后是一個(gè)常量(或者常量表達(dá)式),編譯器在編譯程序時(shí)可以順帶將其結(jié)果計(jì)算出來,而無需等到程序運(yùn)行階段,這樣的優(yōu)化極大地提高了程序的執(zhí)行效率。

到此這篇關(guān)于C++ const與constexpr區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)C++ const constexpr內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解c/c++ 內(nèi)存對(duì)齊

    深入理解c/c++ 內(nèi)存對(duì)齊

    這篇文章主要介紹了c/c++ 內(nèi)存對(duì)齊,有需要的朋友可以參考一下
    2014-01-01
  • C到C++的升級(jí)關(guān)系及區(qū)別實(shí)例探究

    C到C++的升級(jí)關(guān)系及區(qū)別實(shí)例探究

    這篇文章主要為大家介紹了C到C++的升級(jí)關(guān)系及區(qū)別實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • C++報(bào)錯(cuò):Id?returned?1exit?status的解決辦法

    C++報(bào)錯(cuò):Id?returned?1exit?status的解決辦法

    最近剛學(xué)c語言,不止一次遇到了同一種報(bào)錯(cuò),經(jīng)過總結(jié)分享給大家,下面這篇文章主要給大家介紹了關(guān)于C++報(bào)錯(cuò):Id?returned?1exit?status的解決辦法,需要的朋友可以參考下
    2023-04-04
  • QT 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能

    QT 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能

    本文介紹了如何使用QT技術(shù)實(shí)現(xiàn)一個(gè)具有動(dòng)態(tài)效果的隨機(jī)驗(yàn)證碼系統(tǒng),詳述了CaptchaMovableLabel和CaptchaLabel兩個(gè)自定義類的功能,包括顯示和拖動(dòng)字母、繪制噪音點(diǎn)和線條、以及隨機(jī)生成字母等,講解了如何通過繼承QWidget和QLabel來實(shí)現(xiàn)這些功能,并通過MainWindow創(chuàng)建界面
    2024-10-10
  • C++中函數(shù)重載實(shí)例詳解

    C++中函數(shù)重載實(shí)例詳解

    這篇文章主要介紹了C++中函數(shù)重載實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • C++中的類的大小詳解

    C++中的類的大小詳解

    這篇文章主要為大家詳細(xì)介紹了C++中的類的大小,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C++模擬實(shí)現(xiàn)string的示例代碼

    C++模擬實(shí)現(xiàn)string的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C++模擬實(shí)現(xiàn)string的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定的幫助,需要的可以參考一下
    2022-11-11
  • C語言原子操作的實(shí)現(xiàn)示例

    C語言原子操作的實(shí)現(xiàn)示例

    本文主要介紹了C語言中原子操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-12-12
  • 淺談CMake配置OpenCV 時(shí)靜態(tài)鏈接與動(dòng)態(tài)鏈接的選擇

    淺談CMake配置OpenCV 時(shí)靜態(tài)鏈接與動(dòng)態(tài)鏈接的選擇

    下面小編就為大家?guī)硪黄獪\談CMake配置OpenCV 時(shí)靜態(tài)鏈接與動(dòng)態(tài)鏈接的選擇。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • C++與Lua交互原理實(shí)例詳解

    C++與Lua交互原理實(shí)例詳解

    這篇文章主要介紹了C++與Lua交互原理實(shí)例詳解,有感興趣的同學(xué)可以研究下
    2021-02-02

最新評(píng)論

昆明市| 慈溪市| 桐城市| 富平县| 三原县| 江达县| 昆明市| 黄石市| 罗源县| 繁昌县| 沭阳县| 清苑县| 博湖县| 黔西县| 揭东县| 浦江县| 永吉县| 达孜县| 抚顺市| 周至县| 南江县| 张家港市| 云霄县| 海安县| 黎平县| 武威市| 德格县| 忻州市| 鹤山市| 连山| 新蔡县| 曲麻莱县| 贵溪市| 泾阳县| 图们市| 乌拉特前旗| 武义县| 东明县| 苍梧县| 宝鸡市| 收藏|