运算符[]的奇怪行为

Tal*_*don 7 c++

花了最后几天尝试使用C++ operator []方法,我遇到了一个我无法解释的异常现象.下面的代码实现了一个简单的测试字符串类,它允许用户通过其下标"operator"方法访问单个字符.由于我想区分左值和右值下标上下文,"operator"方法返回自定义"CReference"类的实例,而不是标准的C++字符引用.虽然"CReference""operator char()"和"operator =(char)"方法似乎分别处理每个rvalue和lvalue上下文,但g ++拒绝编译而没有记录的附加"operator =(CReference&)"方法下面.虽然添加此方法似乎安抚了某种编译时依赖性,但在程序执行期间从未在运行时实际调用它.

作为一个认为自己已经对C++复杂性有了基本了解的人,这个项目无疑已经证明是一种令人羞愧的体验.如果有人能够看到他们的方式来启发我在这里发生了什么,我会永远感激.与此同时,我将不得不拔出C++书籍,以便在我所知道的和我认为知道的东西之间调和.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Class for holding a reference to type char, retuned by the "operator[](int)"
// method of class "TestString". Independent methods permit differentiation
// between lvalue and rvalue contexts.
class CReference
{
 private:
   char& m_characterReference;

 public:
   // Construct CReference from char&
   CReference(char& m_initialiser)
     : m_characterReference(m_initialiser) {}

   // Invoked when object is referenced in a rvalue char context.
   operator char()
   {
    return m_characterReference;
   }

   // Invoked when object is referenced in a lvalue char= context.
   char operator=(char c)
   {
    m_characterReference = c;
    return c;
   }

   // NEVER INVOKED, but will not compile without! WHY???
   void operator=(CReference &p_assignator){}
};


// Simple string class which permits the manipulation of single characters
// via its "operator[](int)" method.
class TestString
{
 private:
   char m_content[23];

 public:
   // Construct string with test content.
   TestString()
   {
    strcpy(m_content, "This is a test object.");
   }

   // Return pointer to content.
   operator const char*()
   {
    m_content[22] = 0;
    return m_content;
   }

   // Return reference to indexed character.
   CReference operator[](int index)
   {
    return m_content[index];
   }
};


int main(int argc, char *argv[])
{
 TestString s1;

 // Test both lvalue and rvalue subscript access.
 s1[0] = s1[1]; 

 // Print test string.
 printf("%s\n", (const char*)s1);
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

int*_*jay 3

  1. s1[0] = s1[1];如果您自己没有声明的话,这一行会导致编译器为 CReference 生成一个隐式复制赋值运算符。这会导致错误,因为您的类有一个无法复制的引用成员。

  2. 如果您添加了一个采用类型参数的赋值运算符const CReference&,它将被赋值调用。

  3. 在您的代码中,您声明了类型为 的复制赋值运算符void operator=(CReference &p_assignator)。无法调用此方法,因为赋值的右侧是临时对象,无法绑定到非常量引用。但是,声明此运算符的行为会导致编译器不会尝试定义隐式复制赋值运算符,因此避免了先前的编译错误。由于无法调用此运算符,编译器将使用另一个采用 类型参数的赋值运算符char