ITPub博客

首页 > 大数据 > Hadoop > 详解C++引用的使用原理和实例(三)

详解C++引用的使用原理和实例(三)

Hadoop 作者:txf88 时间:2013-08-21 16:39:00 0 删除 编辑

问题弄好了我就想继续更改程序,是程序按照我的设想运行:

第一可以不用引用不?可以用指针,不过相应的地方要改:

StringBad::StringBad(const StringBad *st)

{

    num_strings++; 

 len = st->len;                  // set size

    str = new char[len + 1];          // allot storage

    strcpy(str, st->str);                   // initialize pointer

                       // set object count

    cout << num_strings << ": \"" << str

         << "\" object created\n";    // For Your
Information

}

这个是显示构造函数。

改头文件,再改main中的传值,由于

void callme2(StringBad sb)

{

    cout << "String passed by value:\n";

    cout << "    \"" << sb << "\"\n";

}

因为上面对复制构造函数使用的是指针,如果仍旧用传值,sb=headline2也就是sb=StringBad::StringBad(headline2),指针要求的是
sb=StringBad::StringBad(&headline2),也就是说这个复制构造函数跟没有一样,是问题简单化就这样吧,void
callme2(StringBad sb)编程void callme2(StringBad &sb),用引用!

改过之后的main程序是:

 // vegnews.cpp -- using new and delete with classes

// compile with strngbad.cpp

#include

using std::cout;

#include "stringbad.h"

void callme1(StringBad &);  // pass by reference

void callme2(StringBad &);    // pass by value

int main()

{

    using std::endl;

    StringBad headline1=StringBad::StringBad("Celery Stalks at
Midnight");

    StringBad headline2("Lettuce Prey");

    StringBad sports("Spinach Leaves Bowl for Dollars");

    cout << "headline1: " << headline1 << endl;

    cout << "headline2: " << headline2 << endl;

    cout << "sports: " << sports << endl;

    callme1(headline1);

    cout << "headline1: " << headline1 << endl;

    callme2(headline2);

    cout << "headline2: " << headline2 <<
endl;[Page]

    cout << "Initialize one object to another:\n";

    StringBad sailor =StringBad::StringBad(&sports);

    cout << "sailor: " << sailor << endl;

    cout << "Assign one object to another:\n";

    StringBad knot;

    knot = headline1;

    cout << "knot: " << knot << endl;  

    cout << "End of main()\n";

    return 0;

}

void callme1(StringBad & rsb)

{

    cout << "String passed by reference:\n";

    cout << "    \"" << rsb << "\"\n";

}

void callme2(StringBad &sb)

{

    cout << "String passed by value:\n";

    cout << "    \"" << sb << "\"\n";

}

另一个源文件是:

// strngbad.cpp -- StringBad class methods

#include                    // string.h for some

#include "stringbad.h"

//using std::cout;

using namespace std;

// initializing static class member

int StringBad::num_strings = 0;

// class methods

// construct StringBad from C string

StringBad::StringBad(const char * s)

{

    len = strlen(s);                  // set size

    str = new char[len + 1];          // allot storage

    strcpy(str, s);                   // initialize pointer

    num_strings++;                    // set object count

    cout << num_strings << ": \"" << str

         << "\" object created\n";    // For Your
Information

[NextPage]

StringBad::StringBad()                // default constructor

{

    len = 4;

    str = new char[4];

    strcpy(str, "C++");               // default string

    num_strings++;[Page]

    cout << num_strings << ": \"" << str

         << "\" default object created\n";  // FYI

}

StringBad::~StringBad()               // necessary destructor

{

    cout << "\"" << str << "\" object deleted, ";
   // FYI

    --num_strings;                    // required

    cout << num_strings << " left\n"; // FYI

    delete [] str;                    // required

}

std::ostream & operator<<(std::ostream & os, const StringBad
& st)

{

    os << st.str;

    return os; 

}

StringBad::StringBad(const StringBad *st)

{

    num_strings++; 

 len = st->len;                  // set size

    str = new char[len + 1];          // allot storage

    strcpy(str, st->str);                   // initialize pointer

                       // set object count

    cout << num_strings << ": \"" << str

         << "\" object created\n";    // For Your
Information

}

StringBad & StringBad::operator=(const StringBad  st)

{

    if (this == &st)

        return *this;

    delete [] str;

    len = st.len;

    str = new char[len + 1];

    strcpy(str, st.str);

    return *this;

}

程序执行的时候没有问题,在不给StringBad & StringBad::operator=(const StringBad
 st)函数的参数使用引用的时候程序结果就出现了问题,在最后的析构的时候乱码了!

原因出自下面的    StringBad knot;    knot =
headline1;第一步正确,使用默认的构造函数,第二步就不对了,单步就可以晓得,程序还是调用了StringBad &
StringBad::operator=(const StringBad
 st),即使调用了这个函数也还是要调用复制构造函数的,我步知道为什么,就是这么一回事,上面定义的是指针类型的复制构造函数,不是knot =
headline1需要的,需要的是非指针型的。那么系统就又帮你构造一个隐式的复制函数。[Page]

非指针型的不可以用StringBad::StringBad(const StringBad st),调试就晓得出错了,那么就只能用引用了。

这样:

StringBad::StringBad(const StringBad &st)

{

    num_strings++; 

 len = st.len;                  // set size

    str = new char[len + 1];          // allot storage

    strcpy(str, st.str);                   // initialize pointer

                       // set object count

    cout << num_strings << ": \"" << str

         << "\" object created\n";    // For Your
Information

}

StringBad & StringBad::operator=(const StringBad  st)

{

    if (this == &st)

        return *this;

    delete [] str;

    len = st.len;

    str = new char[len + 1];

    strcpy(str, st.str);

    return *this;

}

或者就这样,把StringBad & StringBad::operator=(const StringBad
 st)改成使用引用参数:

StringBad & StringBad::operator=(const StringBad  &st),这样在knot =
headline1的时候就不用再调用StringBad::StringBad(const StringBad &st),可以直接用StringBad
& StringBad::operator=(const StringBad  &st)达到全部的要求:

[NextPage]

最后结果就是按照我们的目的了!

最后就是全部用引用,这个是最好的方法了!

这样:

StringBad::StringBad(const StringBad &st)

{

    num_strings++; 

 len = st.len;                  // set size

    str = new char[len + 1];          // allot storage

    strcpy(str, st.str);                   // initialize pointer

                       // set object count

    cout << num_strings << ": \"" << str

         << "\" object created\n";    // For Your
Information[Page]

}

StringBad & StringBad::operator=(const StringBad & st)

{

    if (this == &st)

        return *this;

    delete [] str;

    len = st.len;

    str = new char[len + 1];

    strcpy(str, st.str);

    return *this;

}

最后说明一点,使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。 

这个也是efficient c++说明确说明了的一点!

最后说明一点,就是显式复制构造函数跟隐式复制构造函数最大的区别,就是前者由程序员自己定义,一般都会编写成深度复制,而后者就是浅复制。

何谓深度复制?深度复制就是将要被复制的对象,生成一个副本,然后将副本的地址以及数据全部复制,通过strcpy以及strncpy这两个函数实现就像上面的程序:

    len = st.len;                  // set size

    str = new char[len + 1];          // allot storage

    strcpy(str, st.str);                   // initialize pointer

   
而隐式的浅复制就是系统自己生成一个函数然后把对象复制给目标,比如有两个同类对象,跟上面的定义一样,有boo=foo,则是直接把boo.len=foo.len,再boo.str=foo.str。那么可以知道浅复制就是仅仅通过直接的地址赋予而达到给值
的目的,但是隐式函数使用之后就自己销毁自己,也就是析构了,把boo析构了,那么foo的地址还存在?明显在访问foo的时候就有异常了! 

    因此:StringBad knot=headline1;这种情况要给出相对应的正确的显示复制构造函数,而StringBad knot;  
 knot =
headline1;这种情况就更加要给出显示的函数了,而且还要给出默认构造函数,最后还要给出赋值操作符的函数,因为第一句调用默认构造函数,第二句调用赋值操作符,而同时也会调用相应的复制构造函数,因此这个情况要给出3个函数!

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22973305/viewspace-1112159/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2009-12-05