右值引用

左值引用
int i = 0;
int& j = i;

這里的int&是對(duì)左值進(jìn)行綁定(但是int&卻不能綁定右值)狐赡,相應(yīng)的唯竹,對(duì)右值進(jìn)行綁定的引用就是右值引用沸停,他的語法是這樣的 A&&辆影,通過雙引號(hào)來表示綁定類型為A的右值良狈。通過&&我們就可以很方便的綁定右值了后添,比如我們可以這樣綁定一個(gè)右值:

int&& i = 0;

這里我們綁定了一個(gè)右值0,關(guān)于右值的概念會(huì)在后面介紹们颜。右值引用是C++11中新增加的一個(gè)很重要的特性吕朵,他主是要用來解決C++98/03中遇到的兩個(gè)問題:

1:臨時(shí)對(duì)象非必要的昂貴的拷貝操作,

2:是在模板函數(shù)中如何按照參數(shù)的實(shí)際類型進(jìn)行轉(zhuǎn)發(fā)窥突。

通過引入右值引用努溃,很好的解決了這兩個(gè)問題,改進(jìn)了程序性能阻问,后面將會(huì)詳細(xì)介紹右值引用是如何解決這兩個(gè)問題的梧税。

和右值引用相關(guān)的概念比較多,比如:右值、純右值第队、將亡值哮塞、universal references、引用折疊凳谦、移動(dòng)語義忆畅、move語義和完美轉(zhuǎn)發(fā)等等。

int i = getVar();

上面的這行代碼很簡(jiǎn)單尸执,從getVar()函數(shù)獲取一個(gè)整形值家凯,然而,這行代碼會(huì)產(chǎn)生幾種類型的值呢如失?
答案是會(huì)產(chǎn)生兩種類型的值绊诲,一種是左值i,一種是函數(shù)getVar()返回的臨時(shí)值褪贵,這個(gè)臨時(shí)值在表達(dá)式結(jié)束后就銷毀了掂之,而左值i在表達(dá)式結(jié)束后仍然存在,這個(gè)臨時(shí)值就是右值脆丁,具體來說是一個(gè)純右值世舰,右值是不具名的。區(qū)分左值和右值的一個(gè)簡(jiǎn)單辦法是:看能不能對(duì)表達(dá)式取地址偎快,如果能冯乘,則為左值,否則為右值晒夹。

所有的具名變量或?qū)ο蠖际亲笾雕陕涿兞縿t是右值,比如丐怯,簡(jiǎn)單的賦值語句:

int i = 0;

在這條語句中喷好,i 是左值,0 是字面量读跷,就是右值梗搅。在上面的代碼中,i 可以被引用效览,0 就不可以了无切。具體來說上面的表達(dá)式中等號(hào)右邊的0是純右值(prvalue)。

什么是右值

在C++11中所有的值必屬于左值丐枉、將亡值哆键、純右值三者之一。
比如瘦锹,非引用返回的臨時(shí)變量籍嘹、運(yùn)算表達(dá)式產(chǎn)生的臨時(shí)變量闪盔、原始字面量和lambda表達(dá)式等都是純右值。而將亡值是C++11新增的辱士、與右值引用相關(guān)的表達(dá)式泪掀,比如,將要被移動(dòng)的對(duì)象颂碘、T&&函數(shù)返回值异赫、std::move返回值和轉(zhuǎn)換為T&&的類型的轉(zhuǎn)換函數(shù)的返回值等。關(guān)于將亡值我們會(huì)在后面介紹凭涂,先看下面的代碼:

int j = 5;

auto f = []{return 5;};

上面的代碼中5是一個(gè)原始字面量祝辣, []{return 5;}是一個(gè)lambda表達(dá)式贴妻,都是屬于純右值切油,他們的特點(diǎn)是在表達(dá)式結(jié)束之后就銷毀了。
到此為止我們對(duì)右值有了一個(gè)初步的認(rèn)識(shí)名惩,知道了什么是右值澎胡。

右值引用介紹

右值引用的第一個(gè)特點(diǎn)
T&& k = getVar();

第二行代碼和第一行代碼很像,只是相比第一行代碼多了“&&”娩鹉,他就是右值引用攻谁。
我們知道左值引用是對(duì)左值的引用,那么弯予,對(duì)應(yīng)的戚宦,對(duì)右值的引用就是右值引用,而且右值是匿名變量锈嫩,我們也只能通過引用的方式來獲取右值受楼。
雖然這條代碼跟上面介紹的代碼起來差別不大,但是實(shí)際上語義的差別很大呼寸。
這里艳汽,getVar()產(chǎn)生的臨時(shí)值不會(huì)像第一行代碼那樣,在表達(dá)式結(jié)束之后就銷毀了对雪,而是會(huì)被“續(xù)命”河狐,他的生命周期將會(huì)通過右值引用得以延續(xù),和變量k的生命周期一樣長(zhǎng)瑟捣。

codedemo1-1

#include <iostream>
using namespace std;

int g_constructCount=0;
int g_copyConstructCount=0;
int g_destructCount=0;
struct A
{
    A(){
        cout<<"construct: "<<++g_constructCount<<endl;    
    }
    
    A(const A& a)
    {
        cout<<"copy construct: "<<++g_copyConstructCount <<endl;
    }
    ~A()
    {
        cout<<"destruct: "<<++g_destructCount<<endl;
    }
};

A GetA()
{
    return A();
}

int main() {
    A a = GetA();
    return 0;
}

為了清楚的觀察臨時(shí)值馋艺,在編譯時(shí)設(shè)置編譯選項(xiàng)-fno-elide-constructors用來關(guān)閉返回值優(yōu)化效果。

結(jié)果如下:

root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# g++ -o test_left test_left.cpp -fno-elide-constructors
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# ./test_left 
construct: 1
copy construct: 1
destruct: 1
copy construct: 2
destruct: 2
destruct: 3
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# 

從上面的例子中可以看到迈套,在沒有返回值優(yōu)化的情況下捐祠,拷貝構(gòu)造函數(shù)調(diào)用了兩次,一次是GetA()函數(shù)內(nèi)部創(chuàng)建的對(duì)象返回出來構(gòu)造一個(gè)臨時(shí)對(duì)象產(chǎn)生的交汤,另一次是在main函數(shù)中構(gòu)造a對(duì)象產(chǎn)生的雏赦。第二次的destruct是因?yàn)榕R時(shí)對(duì)象在構(gòu)造a對(duì)象之后就銷毀了劫笙。如果開啟返回值優(yōu)化的話,輸出結(jié)果將是:

root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# g++ -o test_left test_left.cpp 
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# ./test_left 
construct: 1
destruct: 1
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# 

可以看到返回值優(yōu)化將會(huì)把臨時(shí)對(duì)象優(yōu)化掉星岗,但這不是c++標(biāo)準(zhǔn)填大,是各編譯器的優(yōu)化規(guī)則。我們?cè)诨氐街疤岬降目梢酝ㄟ^右值引用來延長(zhǎng)臨時(shí)右值的生命周期俏橘,如果上面的代碼中我們通過右值引用來綁定函數(shù)返回值的話允华,結(jié)果又會(huì)是什么樣的呢?在編譯時(shí)設(shè)置編譯選項(xiàng)-fno-elide-constructors寥掐。

int main() {
    A&& a = GetA();
    return 0;
}

結(jié)果:

root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# ./test_left 
construct: 1
copy construct: 1
destruct: 1
destruct: 2
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# 

通過右值引用靴寂,比之前少了一次拷貝構(gòu)造和一次析構(gòu),原因在于右值引用綁定了右值召耘,讓臨時(shí)右值的生命周期延長(zhǎng)了百炬。我們可以利用這個(gè)特點(diǎn)做一些性能優(yōu)化,即避免臨時(shí)對(duì)象的拷貝構(gòu)造和析構(gòu)污它,事實(shí)上剖踊,在c++98/03中,通過常量左值引用也經(jīng)常用來做性能優(yōu)化衫贬。上面的代碼改成:

  const A& a = GetA();

輸出的結(jié)果和右值引用一樣德澈,因?yàn)槌A孔笾狄檬且粋€(gè)“萬能”的引用類型,可以接受左值固惯、右值梆造、常量左值和常量右值。需要注意的是普通的左值引用不能接受右值葬毫,比如這樣的寫法是不對(duì)的:

  A& a = GetA();

上面的代碼會(huì)報(bào)一個(gè)編譯錯(cuò)誤镇辉,因?yàn)榉浅A孔笾狄弥荒芙邮茏笾?/p>

右值引用的第二個(gè)特點(diǎn)

右值引用獨(dú)立于左值和右值。意思是右值引用類型的變量可能是左值也可能是右值供常。比如下面的例子:

int&& var1 = 1; 

var1類型為右值引用摊聋,但var1本身是左值,因?yàn)榫呙兞慷际亲笾怠?/p>

關(guān)于右值引用一個(gè)有意思的問題是:T&&是什么栈暇,一定是右值嗎麻裁?讓我們來看看下面的例子:

template<typename T>
void f(T&& t){}

f(10); 

int x = 10;
f(x); 

從上面的代碼中可以看到,T&&表示的值類型不確定源祈,可能是左值又可能是右值煎源,這一點(diǎn)看起來有點(diǎn)奇怪,這就是右值引用的一個(gè)特點(diǎn)香缺。

右值引用的第三個(gè)特點(diǎn)

T&& t在發(fā)生自動(dòng)類型推斷的時(shí)候手销,它是未定的引用類型(universal references),如果被一個(gè)左值初始化图张,它就是一個(gè)左值锋拖;如果它被一個(gè)右值初始化诈悍,它就是一個(gè)右值,它是左值還是右值取決于它的初始化兽埃。

我們?cè)倩剡^頭看上面的代碼侥钳,對(duì)于函數(shù)template<typename T>void f(T&& t),當(dāng)參數(shù)為右值10的時(shí)候柄错,根據(jù)universal references的特點(diǎn)舷夺,t被一個(gè)右值初始化,那么t就是右值售貌;當(dāng)參數(shù)為左值x時(shí)给猾,t被一個(gè)左值引用初始化,那么t就是一個(gè)左值颂跨。需要注意的是敢伸,僅僅是當(dāng)發(fā)生自動(dòng)類型推導(dǎo)(如函數(shù)模板的類型自動(dòng)推導(dǎo),或auto關(guān)鍵字)的時(shí)候毫捣,T&&才是universal references详拙。再看看下面的例子:

template<typename T>
void f(T&& param); 

template<typename T>
class Test {
    Test(Test&& rhs); 
};

上面的例子中,param是universal reference蔓同,rhs是Test&&右值引用,因?yàn)槟0婧瘮?shù)f發(fā)生了類型推斷蹲诀,而Test&&并沒有發(fā)生類型推導(dǎo)斑粱,因?yàn)門est&&是確定的類型了。

正是因?yàn)橛抑狄每赡苁亲笾狄部赡苁怯抑蹈Γ蕾囉诔跏蓟虮保⒉皇且幌伦泳痛_定的特點(diǎn),我們可以利用這一點(diǎn)做很多文章痕慢,比如后面要介紹的移動(dòng)語義和完美轉(zhuǎn)發(fā)尚揣。

這里再提一下引用折疊,正是因?yàn)橐肓擞抑狄靡淳伲钥赡艽嬖谧笾狄门c右值引用和右值引用與右值引用的折疊快骗,C++11確定了引用折疊的規(guī)則,規(guī)則是這樣的:

-所有的右值引用疊加到右值引用上仍然還是一個(gè)右值引用塔次;
-所有的其他引用類型之間的疊加都將變成左值引用方篮。

右值引用的作用

demo1-2

T(T&& a) : m_val(val){ a.m_val=nullptr; }

這行代碼實(shí)際上來自于一個(gè)類的構(gòu)造函數(shù),構(gòu)造函數(shù)的一個(gè)參數(shù)是一個(gè)右值引用励负,為什么將右值引用作為構(gòu)造函數(shù)的參數(shù)呢藕溅?在解答這個(gè)問題之前我們先看一個(gè)例子。如代碼清單1-2所示继榆。

#include <iostream>
using namespace std;
class A
{
public:
    A():m_ptr(new int(0)){cout << "construct" << endl;}
    A(const A& a):m_ptr(new int(*a.m_ptr)) //深拷貝的拷貝構(gòu)造函數(shù)
    {
        cout << "copy construct" << endl;
    }
    ~A(){ delete m_ptr;}
private:
    int* m_ptr;
};

A GetA()
{
    return A();
}
int main() {
    A a = GetA();
    return 0;
}

輸出結(jié)果

root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# g++ -o right_ref_test right_ref_test.cpp -fno-elide-constructors
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# ./right_ref_test construct
copy construct
copy construct
root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# 

這個(gè)例子很簡(jiǎn)單巾表,一個(gè)帶有堆內(nèi)存的類汁掠,必須提供一個(gè)深拷貝拷貝構(gòu)造函數(shù),因?yàn)槟J(rèn)的拷貝構(gòu)造函數(shù)是淺拷貝集币,會(huì)發(fā)生“指針懸掛”的問題调塌。如果不提供深拷貝的拷貝構(gòu)造函數(shù),上面的測(cè)試代碼將會(huì)發(fā)生錯(cuò)誤(編譯選項(xiàng)-fno-elide-constructors)惠猿。

內(nèi)部的m_ptr將會(huì)被刪除兩次羔砾,一次是臨時(shí)右值析構(gòu)的時(shí)候刪除一次,第二次外面構(gòu)造的a對(duì)象釋放時(shí)刪除一次偶妖,而這兩個(gè)對(duì)象的m_ptr是同一個(gè)指針姜凄,這就是所謂的指針懸掛問題。提供深拷貝的拷貝構(gòu)造函數(shù)雖然可以保證正確趾访,但是在有些時(shí)候會(huì)造成額外的性能損耗态秧,因?yàn)橛袝r(shí)候這種深拷貝是不必要的。
上面代碼中的GetA函數(shù)會(huì)返回臨時(shí)變量扼鞋,然后通過這個(gè)臨時(shí)變量拷貝構(gòu)造了一個(gè)新的對(duì)象a申鱼,臨時(shí)變量在拷貝構(gòu)造完成之后就銷毀了,如果堆內(nèi)存很大的話云头,那么捐友,這個(gè)拷貝構(gòu)造的代價(jià)會(huì)很大,帶來了額外的性能損失溃槐。每次都會(huì)產(chǎn)生臨時(shí)變量并造成額外的性能損失匣砖,有沒有辦法避免臨時(shí)變量造成的性能損失呢?看看下面的代碼昏滴。

demo1-3

class A
{
public:
    A() :m_ptr(new int(0)){}
    A(const A& a):m_ptr(new int(*a.m_ptr)) //深拷貝的拷貝構(gòu)造函數(shù)
    {
        cout << "copy construct" << endl;
    }
    A(A&& a) :m_ptr(a.m_ptr)
    {
        a.m_ptr = nullptr;
        cout << "move construct" << endl;
    }
    ~A(){ delete m_ptr;}
private:
    int* m_ptr;
};
int main(){
    A a = Get(false); 
} 
輸出:
construct
move construct
move construct

這個(gè)構(gòu)造函數(shù)并沒有做深拷貝猴鲫,僅僅是將指針的所有者轉(zhuǎn)移到了另外一個(gè)對(duì)象,同時(shí)谣殊,將參數(shù)對(duì)象a的指針置為空拂共,這里僅僅是做了淺拷貝,因此姻几,這個(gè)構(gòu)造函數(shù)避免了臨時(shí)變量的深拷貝問題宜狐。

上面這個(gè)函數(shù)其實(shí)就是移動(dòng)構(gòu)造函數(shù),他的參數(shù)是一個(gè)右值引用類型鲜棠,這里的A&&表示右值肌厨,為什么?前面已經(jīng)提到豁陆,這里沒有發(fā)生類型推斷柑爸,是確定的右值引用類型。為什么會(huì)匹配到這個(gè)構(gòu)造函數(shù)盒音?因?yàn)檫@個(gè)構(gòu)造函數(shù)只能接受右值參數(shù)表鳍,而函數(shù)返回值是右值馅而,所以就會(huì)匹配到這個(gè)構(gòu)造函數(shù)。這里的A&&可以看作是臨時(shí)值的標(biāo)識(shí)譬圣,對(duì)于臨時(shí)值我們僅僅需要做淺拷貝即可瓮恭,無需再做深拷貝,從而解決了前面提到的臨時(shí)變量拷貝構(gòu)造產(chǎn)生的性能損失的問題厘熟。這就是所謂的移動(dòng)語義屯蹦,右值引用的一個(gè)重要作用是用來支持移動(dòng)語義的

需要注意的一個(gè)細(xì)節(jié)是绳姨,我們提供移動(dòng)構(gòu)造函數(shù)的同時(shí)也會(huì)提供一個(gè)拷貝構(gòu)造函數(shù)登澜,以防止移動(dòng)不成功的時(shí)候還能拷貝構(gòu)造,使我們的代碼更安全飘庄。

我們知道移動(dòng)語義是通過右值引用來匹配臨時(shí)值的脑蠕,那么,普通的左值是否也能借助移動(dòng)語義來優(yōu)化性能呢跪削,那該怎么做呢谴仙?事實(shí)上C++11為了解決這個(gè)問題,提供了std::move方法來將左值轉(zhuǎn)換為右值碾盐,從而方便應(yīng)用移動(dòng)語義晃跺。move是將對(duì)象資源的所有權(quán)從一個(gè)對(duì)象轉(zhuǎn)移到另一個(gè)對(duì)象,只是轉(zhuǎn)移廓旬,沒有內(nèi)存的拷貝哼审,這就是所謂的move語義。

{
    std::list< std::string> tokens;
    //省略初始化...
    std::list< std::string> t = tokens; //這里存在拷貝 
}
std::list< std::string> tokens;
std::list< std::string> t = std::move(tokens);  //這里沒有拷

如果不用std::move孕豹,拷貝的代價(jià)很大,性能較低十气。使用move幾乎沒有任何代價(jià)励背,只是轉(zhuǎn)換了資源的所有權(quán)。他實(shí)際上將左值變成右值引用砸西,然后應(yīng)用移動(dòng)語義叶眉,調(diào)用移動(dòng)構(gòu)造函數(shù),就避免了拷貝芹枷,提高了程序性能衅疙。如果一個(gè)對(duì)象內(nèi)部有較大的對(duì)內(nèi)存或者動(dòng)態(tài)數(shù)組時(shí),很有必要寫move語義的拷貝構(gòu)造函數(shù)和賦值函數(shù)鸳慈,避免無謂的深拷貝饱溢,以提高性能。事實(shí)上走芋,C++11中所有的容器都實(shí)現(xiàn)了移動(dòng)語義绩郎,方便我們做性能優(yōu)化潘鲫。

template<typename T>
typename remove_reference<T>::type&& move(T&& value){
    return static_cast<typename remove_reference<T>::type&&>(value);
}

type:是C++11新增的 類型成員 類型成員與靜態(tài)成員一樣,它們都屬于類而不屬于對(duì)象肋杖,訪問它時(shí)也與訪問靜態(tài)成員一樣用::訪問
它表達(dá)的意思是返回remove_reference類的type類型成員溉仑。而該類是一個(gè)模板類,所以在它前面要加typename關(guān)鍵字状植。
remove_reference類其實(shí)就是就是通過模板去除引用

template <typename T>
struct remove_reference{
    typedef T type;  //定義T的類型別名為type
};

template <typename T>
struct remove_reference<T&> //左值引用
{
    typedef T type;
}

template <typename T>
struct remove_reference<T&&> //右值引用
{
   typedef T type;
}

通過上面的代碼我們可以知道浊竟,經(jīng)過remove_reference處理后,T的引用被剔除了津畸。假設(shè)前面我們通過move的類型自動(dòng)推導(dǎo)得到T為int&&振定,那么再次經(jīng)過模板推導(dǎo)remove_reference的type成員,這樣就可以得出type的類型為int了洼畅。

經(jīng)過翻譯后的代碼

int && move(int&& && t){
    return static_case<int&&>(t);
}

//或
int && move(int& && t){
    return static_case<int&&>(t);
}

具體解釋可看:C++高階知識(shí) std::move

完美轉(zhuǎn)發(fā)

直接看看代碼:
demo1-4

#include <iostream>


template<typename T>
void print(T && t){
    std::cout << "右值" << std::endl;
}

template<typename T>
void print(T & t){
    std::cout << "左值" << std::endl;
}

template<typename T>
void testForward(T && v){
    print(v);
    print(std::forward<T>(v));
    print(std::move(v));
}

int main(int argc, char * argv[])
{
    testForward(1);

    std::cout << "======================" << std::endl;

    int x = 1;
    testForward(x);

    return 0;
}

運(yùn)行結(jié)果:

root@iZuf65i08ucxtob67o6urwZ:/usr/myC++/shared_ptr# ./forward_test2
左值
右值
右值
======================
左值
左值
右值

原理

template <typename T>
T&& forward(typename std::remove_reference<T>::type& param)
{
    return static_cast<T&&>(param);
}

template <typename T>
T&& forward(typename std::remove_reference<T>::type&& param)
{
    return static_cast<T&&>(param);
}

forward實(shí)現(xiàn)了兩個(gè)模板函數(shù)吩案,一個(gè)接收左值,另一個(gè)接收右值帝簇。在上面有代碼中:

typename std::remove_reference<T>::type

其含義就是獲得去掉引用的參數(shù)類型徘郭。所以上面的兩上模板函數(shù)中,第一個(gè)是左值引用模板函數(shù)丧肴,第二個(gè)是右值引用模板函數(shù)残揉。
緊接著std::forward模板函數(shù)對(duì)傳入的參數(shù)進(jìn)行強(qiáng)制類型轉(zhuǎn)換,轉(zhuǎn)換的目標(biāo)類型符合引用折疊規(guī)則芋浮,因此左值參數(shù)最終轉(zhuǎn)換后仍為左值抱环,右值參數(shù)最終轉(zhuǎn)成右值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纸巷,一起剝皮案震驚了整個(gè)濱河市镇草,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瘤旨,老刑警劉巖梯啤,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異存哲,居然都是意外死亡因宇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門祟偷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來察滑,“玉大人,你說我怎么就攤上這事修肠『爻剑” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)魂爪。 經(jīng)常有香客問我先舷,道長(zhǎng),這世上最難降的妖魔是什么滓侍? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任蒋川,我火速辦了婚禮,結(jié)果婚禮上撩笆,老公的妹妹穿的比我還像新娘捺球。我一直安慰自己,他們只是感情好夕冲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布氮兵。 她就那樣靜靜地躺著,像睡著了一般歹鱼。 火紅的嫁衣襯著肌膚如雪泣栈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天弥姻,我揣著相機(jī)與錄音南片,去河邊找鬼。 笑死庭敦,一個(gè)胖子當(dāng)著我的面吹牛疼进,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秧廉,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼伞广,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了疼电?” 一聲冷哼從身側(cè)響起嚼锄,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔽豺,沒想到半個(gè)月后灾票,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茫虽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年血崭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奠货。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扫步。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡檬某,死狀恐怖委煤,靈堂內(nèi)的尸體忽然破棺而出简识,到底是詐尸還是另有隱情瓤摧,我是刑警寧澤只洒,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站盾致,受9級(jí)特大地震影響主经,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庭惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一罩驻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧护赊,春花似錦惠遏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至判耕,卻和暖如春透绩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壁熄。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工帚豪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人请毛。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓志鞍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親方仿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子固棚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容