简体   繁体   English

为读取和写入定义operator []

[英]defining operator [ ] for both reading and writing

In the book of "The C++ Programming Language", the author gave the following example along with several statements: 在“The C ++ Programming Language”一书中,作者给出了以下示例以及几个语句:

Defining an operator, such as [], to be used for both reading and writing is difficult where it is not acceptable simply to return a reference and let the user decide what to do with it. 如果仅仅返回引用并让用户决定如何处理它是不可接受的,那么定义用于读取和写入的操作符(例如[])是很困难的。

Cref, is to help implement a subscript operator that distinguishes between reading and writing. Cref,是帮助实现区分阅读和写作的下标操作符。

Why [] is difficult to be defined when to be used for both reading and writing? 为什么[]难以定义何时用于读写? How does the definition of class Cref help to solve this issue? 类Cref的定义如何帮助解决这个问题?

  class String{
     struct Srep; 
     Srep *rep; 

     public: 
        class Cref;

     // some definitions here
     void check (int i) const { if (i<0 || rep->sz<=i) throw Range( );}

     char read( int i) const {return rep->s[i];}
     void write(int i, char c){ rep=rep->get_own_copy(); rep->s[i]=c;}

     Cref operator[] (int i){ check(i); return Cref(*this, i);}
     char operator[] (int i) const{check(i); return rep->s{i];}

   }

  class String::Cref{
    friend class String;
          String& s;
          int i;
          Cref(String& ss, int ii): s(ss),i(ii) {}
    public:
          operator char( ) { return s.read(i);}
          void operator=(char c){s.write(i,c);}
  };

If you don't define a class Cref that solves this issue, then you have to do what std::map does: 如果您没有定义解决此问题的类Cref ,那么您必须执行std::map所做的事情:

template class <K,V> class map{
   V& operator[](K const & key);
}

This returns a reference, which must be backed by a valid memory location, and therefore 这将返回一个引用,该引用必须由有效的内存位置支持,因此

std::map<string,string> m;
m["foo"];
assert(m.find("foo") != m.end());

The assertion will succeed (meaning, "foo" is now a valid key in the map) even though you never assigned something to m["foo"] . 断言将成功(意思是, "foo"现在是地图中的有效键),即使您从未向m["foo"]分配内容。

This counterintuitive behavior can be fixed by the Cref class in your example -- it can perform the appropriate logic to create m["foo"] only when you assign to the reference, and ensure that m.find("foo") == m.end() if you didn't perform some assignment when you tried to read the nonexistant m["foo"] . 这种违反直觉的行为可以通过示例中的Cref类来修复 - 只有在分配给引用时才能执行适当的逻辑来创建m["foo"] ,并确保m.find("foo") == m.end()如果你在尝试读取不存在的m["foo"]时没有执行某些赋值。

Likewise, in your String class (which is a reference-counted string -- strings share their string data, and a new copy is created when you change a string whose data is shared with another string), you'd have to make a copy when using operator[] to read characters. 同样,在String类中(这是一个引用计数字符串 - 字符串共享其字符串数据,并且当您更改其数据与另一个字符串共享的字符串时创建一个新副本),您必须制作一个副本当使用operator[]读取字符时。 The use of the Cref class, allows you to ensure that you only make a copy when using operator[] to write. 使用Cref类,可以确保在使用operator[]编写时只进行复制。

String s;
s[0] = 5;

will call String::operator [](int) and then String::Cref::operator =(char) . 将调用String::operator [](int) ,然后调用String::operator [](int) String::Cref::operator =(char)

However, 然而,

String s;
char c = s[0];

will call String::operator [](int) and then String::Cref::operator char() . 将调用String::operator [](int) ,然后调用String::operator [](int) String::Cref::operator char()

When reading, String::Cref::operator char is called, and when writing String::Cref::operator = is called - this allows you to distinguish between reading and writing. 在读取时,调用String::Cref::operator char ,并且在调用String::Cref::operator = ,这允许您区分读取和写入。

Why [] is difficult to be defined when to be used for both distinguish between reading and writing? 当用于 区分阅读和写作 时, 为什么难以 定义 []?

It's because the non-const operator[] is called whenever you have a non-const object, even if you're using it in a read-only fashion. 这是因为只要你有一个非const对象就会调用非const operator[] ,即使你是以只读方式使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM