下面的代码来自c++ primer plus第5版第12章,书中代码写的非常好:

// string1.h -- fixed and augmented string class definition
#include <iostream>
using std::ostream;
using std::istream; #ifndef STRING1_H_
#define STRING1_H_
class String
{
private:
char * str; // pointer to string
int len; // length of string
static int num_strings; // number of objects
static const int CINLIM = ; // cin input limit
public:
// constructors and other methods
String(const char * s); // constructor
String(); // default constructor
String(const String &); // copy constructor
~String(); // destructor
int length () const { return len; }
// overloaded operator methods
String & operator=(const String &);
String & operator=(const char *);
char & operator[](int i);
const char & operator[](int i) const;
// overloaded operator friends
friend bool operator<(const String &st, const String &st2);
friend bool operator>(const String &st1, const String &st2);
friend bool operator==(const String &st, const String &st2);
friend ostream & operator<<(ostream & os, const String & st);
friend istream & operator>>(istream & is, String & st);
// static function
static int HowMany();
};
#endif
num_strings 主要是为了统计对象创建的个数.
cpp文件:
// string1.cpp -- String class methods
#include <cstring> // string.h for some
#include "string1.h" // includes <iostream>
using std::cin;
using std::cout; // initializing static class member int String::num_strings = ; // static method
int String::HowMany()
{
return num_strings;
} // class methods
String::String(const char * s) // construct String from C string
{
len = std::strlen(s); // set size
str = new char[len + ]; // allot storage
std::strcpy(str, s); // initialize pointer
num_strings++; // set object count
} String::String() // default constructor
{
len = ;
str = new char[];
str[] = '\0'; // default string
num_strings++;
} String::String(const String & st)
{
num_strings++; // handle static member update
len = st.len; // same length
str = new char [len + ]; // allot space
std::strcpy(str, st.str); // copy string to new location
} String::~String() // necessary destructor
{
--num_strings; // required
delete [] str; // required
} // overloaded operator methods // assign a String to a String
String & String::operator=(const String & st)
{
if (this == &st)
return *this;
delete [] str;
len = st.len;
str = new char[len + ];
std::strcpy(str, st.str);
return *this;
} // assign a C string to a String
String & String::operator=(const char * s)
{
delete [] str;
len = std::strlen(s);
str = new char[len + ];
std::strcpy(str, s);
return *this;
} // read-write char access for non-const String
char & String::operator[](int i)
{
return str[i];
} // read-only char access for const String
const char & String::operator[](int i) const
{
return str[i];
} // overloaded operator friends bool operator<(const String &st1, const String &st2)
{
return (std::strcmp(st1.str, st2.str) < );
} bool operator>(const String &st1, const String &st2)
{
return st2.str < st1.str;
} bool operator==(const String &st1, const String &st2)
{
return (std::strcmp(st1.str, st2.str) == );
} // simple String output
ostream & operator<<(ostream & os, const String & st)
{
os << st.str;
return os;
} // quick and dirty String input
istream & operator>>(istream & is, String & st)
{
char temp[String::CINLIM];
is.get(temp, String::CINLIM);
if (is)
st = temp;
while (is && is.get() != '\n') //  丢弃多余的字符
continue;
return is;
}

代码有许多值得注意的地方:

1.为什么构造函数里面是

str = new char[1];
str[0] = '\0';
而不是
str=new char;
上面2中方式分配的内存量相同,区别在于前者与析构函数兼容,而后者不兼容。析构函数含有如下代码:
delete[] str;
delete[] 与使用new【】初始化的指针和空指针都兼容,因此对于下面的代码:
str = new char[1];
str[0] = '\0';
可修改为
str=0;//set str to the null pointer

对于以其他方式初始化的指针,使用delete[] 删除,结果是不确定的:

char words[15]="ab";

char *p=words;

char *p2=new char;

char *p3;

delete[] p1; //undefined,so don't do it //会产生run time error

delete[] p2;//undefined,so don't do it

delete[] p3;//undefined,so don't do it 会产生run time error.

上面几种方式都不正确。

2.为什么我们要2次重载:

// read-write char access for non-const String
char & String::operator[](int i)
{
return str[i];
}

// read-only char access for const String
const char & String::operator[](int i) const
{
return str[i];
}

是因为如果没有重载常量的[],下面的代码将出错:

const String s("hello");

cout<<a[1];

元素是s是常量,而上述方法无法确保不修改数据。

所以在重载时,c++将区分常量和非常量函数的特征标

有了上述的重载后,

const string s("helloo");

cin>>s[1];就会报错。

istream的get函数有许多重载版本:

single character (1)
  int get();
  istream& get (char& c);
c-string (2)
  istream& get (char* s, streamsize n);
  istream& get (char* s, streamsize n, char delim);
stream buffer (3)
  istream& get (streambuf& sb);
  istream& get (streambuf& sb, char delim);

cin.get()读取单个字符并返回,http://www.cplusplus.com/reference/istream/istream/get/

可不可以将构造函数换成:

String()

{

str="default string";

len=strlen(str);

}

答:不可以,没有使用new[]来初始化str,对默认对象调用析构函数时,使用delete【】来释放,对不是使用new初始化的指针使用

delete,其结果将是不确定的,并可能是有害的。

在构造函数中使用new应注意的问题

使用new来初始化对象的指针成员时必须要特别小心,具体地说,应该是这样:

1.如果在构造函数中使用new来初始化成员指针,则应在析构中调用delete

2,new和delete必须相互兼容,new对于delete,new[]对于delete[]。

3.如果有多个构造函数,则必须以相同的方式使用new,要么带中括号,要么都不带。因为只有一个析构函数,因此所有的构造函数都必须与他兼容。不过,可以在一个构造函数中使用new来初始化指针,而在另一个构造函数中将指针初始化为空(null或0,这是

因为delete(无论是带【】还是不带【】)都可以用于空指针

ostream & operator<<(ostream & os, const String & st) 
可以可以不返回引用?
答:绝对不可以
cout一般都可以链式操作cout<<s<<s2;
如果不返回引用,如果返回类型为ostream,将要求ostream类的复制构造函数,而ostream没有任何公有的复制构造函数。幸运的是,
返回一个指向cout的引用不会带来任何问题。
如果不写成引用,编译不通过。报错:
无法访问 private 成员(在“std::basic_ios<_Elem,_Traits>”类中声明)
我们在xiobase文件中科院看到:
private:
ios_base& __CLR_OR_THIS_CALL operator=(const ios_base& _Right)
 private: ios_base(const ios_base&);
显然,拷贝构造函数与复制操作符都声明为私有。 因此,重载操作符应该如下: ostream& operator<<(ostream &out , CA &ca) istream也是如此。

测试:

这是书本的测试:

// sayings1.cpp -- using expanded String class
// compile with string1.cpp
#include <iostream>
#include "string1.h"
const int ArSize = ;
const int MaxLen =;
int main()
{
using std::cout;
using std::cin;
using std::endl;
String name;
cout <<"Hi, what's your name?\n>> ";
cin >> name; cout << name << ", please enter up to " << ArSize
<< " short sayings <empty line to quit>:\n";
String sayings[ArSize]; // array of objects
char temp[MaxLen]; // temporary string storage
int i;
for (i = ; i < ArSize; i++)
{
cout << i+ << ": ";
cin.get(temp, MaxLen);
while (cin && cin.get() != '\n')
continue;
if (!cin || temp[] == '\0') // empty line?
break; // i not incremented
else
sayings[i] = temp; // overloaded assignment
}
int total = i; // total # of lines read cout << "Here are your sayings:\n";
for (i = ; i < total; i++)
cout << sayings[i][] << ": " << sayings[i] << endl; int shortest = ;
int first = ;
for (i = ; i < total; i++)
{
if (sayings[i].length() < sayings[shortest].length())
shortest = i;
if (sayings[i] < sayings[first])
first = i;
}
cout << "Shortest saying:\n" << sayings[shortest] << endl;;
cout << "First alphabetically:\n" << sayings[first] << endl;
cout << "This program used "<< String::HowMany()
<< " String objects. Bye.\n"; return ;
}

这是我的测试;

#include"String.h"
#include<cassert>
#include<string> int main()
{ //copy constrtor
String s1("abc");
cout<<s1<<endl; String s2(s1);
cout<<s2<<endl; // operator=(const char* s);
s1="helloworld";
cout<<s1<<endl;
// operator=(const String & other);
String s3("youcan");
s1=s3;
cout<<s1<<endl; //调用赋值构造函数
String s4="dddd";
cout<<s4<<endl;
cout<<s1.howMany()<<endl;//输出4 String s5="helloworld";
cout<<s5[]<<endl;
s5[]='z';
cout<<s5<<endl;
const String s6("const");
cout<<s6[]<<endl; }

上面的全都来自c++ primer plus这本书。

STL string 模拟的更多相关文章

  1. 深入剖析 linux GCC 4.4 的 STL string

    转自: 深入剖析 linux GCC 4.4 的 STL string 本文通过研究STL源码来剖析C++中标准模板块库std::string运行机理,重点研究了其中的引用计数和Copy-On-Wri ...

  2. 格式字符串分配stl::string

    代码非常easy,不解释,直接在代码: #include <cstdio> #include <cstdarg> #include <iostream> using ...

  3. 浅谈C++ STL string容器

    浅谈C++ STL string容器 本篇随笔简单讲解一下\(C++STL\)中\(string\)容器的使用方法及技巧. string容器的概念 其实\(string\)并不是\(STL\)的一种容 ...

  4. C++标准模板库Stand Template Library(STL)简介与STL string类

    参考<21天学通C++>第15和16章节,在对宏和模板学习之后,开启对C++实现的标准模板类STL进行简介,同时介绍简单的string类.虽然前面对于vector.deque.list等进 ...

  5. 转C++之stl::string写时拷贝导致的问题

    前几天在开发某些数据结构到文件的 Dump 和 Load 功能的时候, 遇到的一个 bug . [问题复现] 问题主要出在 Load 过程中,从文件读取数据的时候, 直接使用 fread 的去操作 s ...

  6. stl string

    10.2.1 STL的string 1String概念 ²  string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都 ...

  7. 洛谷 P1739 表达式括号匹配【STL/stack/模拟】

    题目描述 假设一个表达式有英文字母(小写).运算符(+,-,*,/)和左右小(圆)括号构成,以"@"作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返 ...

  8. [转载] C++ STL string的Copy-On-Write技术

    原文: http://coolshell.cn/articles/12199.html stl的string是经过严格优化的, 深入理解对以后编程过程中应用string非常有益处, 感谢左耳朵耗子的精 ...

  9. [转] 深入剖析 linux GCC 4.4 的 STL string

    本文通过研究STL源码来剖析C++中标准模板块库std::string运行机理,重点研究了其中的引用计数和Copy-On-Write技术. 平台:x86_64-redhat-linux gcc ver ...

随机推荐

  1. HDU 1002 A + B Problem II(大整数相加)

    A + B Problem II Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u De ...

  2. 7kb的javascript日期操作类库(XDate)

    A Modern JavaScript Date Library XDate is a thin wrapper around JavaScript's native Date object that ...

  3. 微型 ORM 的第一篇 DapperLambda发布

    引言:因为接触过多个ORM,但使用的时候都遇到了各自的一些不够理想的地方,从最早开始开始公司自己分装的,到后面用EF,以及Dapper和DapperExtensions  到现在用的FluentDat ...

  4. Sql日期时间格式转换 备用

    sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-0 ...

  5. InfoQ文章

    http://www.infoq.com/cn/presentations/log-platform-construction-weipinhui https://github.com/Telesco ...

  6. 模拟美萍加密狗--Rockey2虚拟狗(四)

    目录(?)[+]       首先,抱怨一下.学校个破网,似乎把我端口封了,死活分不上IP,也许是是我MAC改的太频繁了,有盗号嫌疑…… 然后,正文开始…… 其实虚拟狗几天前就写完了,可这几天上不了网 ...

  7. MFC模式对话框与非模式对话框 消息处理顺序

    对话框有两种创建方式:DoModal和Creat. 其中DoModal创建的是模态的对话框,而Creat创建的是非模态的对话框下面总结下他们的不同. 对于模态的对话框,在该对话框被关闭前,用户将不能在 ...

  8. 基于Visual C++2013拆解世界五百强面试题--题10-找出N个数种最大的K个数

    有一亿个整数,请找出最大的 1000 个,要求时间越短越好, 空间占用越好越好. 如果不考虑时间效率,很容易想到解决方法,我们只需存储前一千个数, 然后依次读入后面的数和这一千个数组比较,替换其中比较 ...

  9. hdoj 3062 Party(2-SAT)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3062 思路分析:将问题转换为2-SAT问题,需要注意的是将命题转换为有向图的方法:命题中A1, A2, ...

  10. 用elasticsearch索引mongodb数据

    参照网页:单机搭建elasticsearch和mongodb的river 三个步骤: 一,搭建单机replicSet二,安装mongodb-river插件三,创建meta,验证使用 第一步,搭建单机m ...