使用环境:
ubuntu 11.10 C++
自己创建了一个套接字的类MySock
当调用Accept()方法时,返回一个MySock &类型的值;
MySock & Accept();
出现错误:
MySock connSock=lstnSock.Accept();
当调用connSock.Recv();方法进行接收时,接收到的字节数为-1(即接收错误);
提示错误为:EBADF: The argument sockfd is an invalid descriptor.
代码:
MySock & MySock::Accept() { MySock newSock; if(m_fdSock==-1) { printf("Failed to create socket\n"); return newSock; } int sockfd=accept(m_fdSock, NULL, NULL); //接收失败 if(sockfd==-1) { int tempErrno=errno; printAcceptErrorInfo(tempErrno); return newSock; } //注意:可以访问该类对象的私有成员 newSock.m_fdSock=sockfd; return newSock; }
于是进行调试,发现调用底层函数recv(int fdsock, void * buf, size_t bufsize, int flags);中的fdsock也是有效的值,也就是不是无效的套接字
错误分析:
在Accept()方法中,创建了一个局部变量:MySock类对象,其有效的生命周期的Accept()方法
也就是说,Accept()方法结束之后,该局部变量生命周期结束,可能会被销毁,返回该对象的引用就会引用到一个无效的值,从而引起错误;
把Accept()的返回值修改为MySock类型,正确
小结:
当时返回类型为引用类型,主要是出于这样的考虑:如果返回的是对象的话,实际上会有一个隐性的赋值操作,也就是说,返回的其实是Accept()方法中创建的对象的一个复制品,如果包含指针的话会指向同一块内存空间(现在看来,没必要这样担心,因为指向同一块内存空间并不会有问题)
可以参考“重载赋值操作符”一文进行阅读
在重载赋值操作符operator=()中返回一个引用类型,是因为调用operator=()的对象是在operator=()中创建的,不会有生命周期的担心