花了最后几天尝试使用C操作符[]方法,我遇到了一个我无法解释的异常现象.下面的代码实现了一个简单的测试字符串类,它允许用户通过其下标“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; }
解决方法
>行s1 [0] = s1 [1];如果您没有自己声明CReference,则会导致编译器为CReference生成隐式复制赋值运算符.这会导致错误,因为您的类具有无法复制的引用成员. >如果添加了一个带有const CReference&类型参数的赋值运算符,它将被赋值调用. >在您的代码中,您声明了一个类型为void operator =(CReference& p_assignator)的复制赋值运算符.这不能被调用,因为赋值的右侧是临时对象,不能绑定到非const引用.但是,声明此运算符的行为会导致编译器不尝试定义隐式复制赋值运算符,从而避免了先前的编译错误.由于无法调用此运算符,因此编译器会转到另一个带有char类型参数的赋值运算符.