C++中<<运算符重载中的问题

ostream & operator<<(ostream &out) const
{
    if(str != NULL)
    {
          out << str;
    }
    return out;
}

上述代码中最后为啥要return out这个操作
而且假设现在有一个对象S
S << cout和cout << S这俩玩意一样不 这个C++这块好难理解啊

不是一样的。那个operator重载的第一个参数就是ostream对象。
就像:

ostream& operator(ostream& os, ClassA a){
  //………………
  return os;
}

如果使用以下代码:

ClassA cla;
cout << cla; //等价于operator<<(cout,cla);

那么传入operator<<的参数中,os是cout,a就是cla。
至于你写到运算符只有一个参数,然而<<是二元运算符,所以你这个应该定义在类里。
而且如果定义在类里,就要将对象放在运算符前面,而且cout没有定义那种运算符。
就像:

class S{
public:
  std::ostream& operator<<(std::ostream& os){ //标记:1
    //insert your code
    return os;
  }
};

std::ostream& operator<<(std::ostream& os,S s){ //标记:2
  //insert your code
  return os;
}
int main(){
  using namespace std;
  S s;
  cout << s; //调用2
  s << cout; //调用1
}

输入输出流operator>>(), operator<<()运算符重载函数还是返回输入输出流本身的引用,是为了可以使用级联调用,例如
cout << a << b << c; 等价于operator<<(operator<<(operator<<(cout, a), b), c);
cin >> a >> b >> c;等价于operator>>(operator>>(operator>>(cout, a), b), c);
因为>>, <<的结合律是从左到右,要实现级联调用,输入输出流必须是operator>>()operator<<()函数的第一个参数,

返回out为了实现连续输出,即cout<<a<<b<<c;

ostream& out为定义一个名字为out的引用型输出流对象
out 就可以类比 cout 标准的输出流对象
如果str非空
out<<str; 就是输出str
如果str空
返回out return out 就相当于return 0

以上仅供参考,如有任何疑问,可以评论回复,看到即回。
希望对题主有所帮助!可以的话,点个采纳!