Thanks for your valuable suggestions, here is my revised code.
Code:
class MyString
{
public:
	MyString& operator=(const MyString& rhs)
	{
		if(this != &rhs)			
			strcpy_s(m_str,strlen(rhs.m_str)+1, rhs.m_str);

		return *this;
	}

	MyString(const MyString& rhs)
	{
		m_str = new char[strlen(rhs.m_str)+1];
		strcpy_s(m_str,strlen(rhs.m_str)+1, rhs.m_str);
	}

	MyString(const char* str) 
	{
		m_str = new char[strlen(str)+1];
		strcpy_s(m_str,strlen(str)+1, str);
	}

	MyString()
	{
		m_str = new char[1024];
	}

	~MyString()
	{
		delete[] m_str;
	}

	friend MyString operator+(MyString& a, const MyString& b);
    friend ostream& operator<<(ostream& os, const MyString& str);
	
private:
	char* m_str;
};

MyString operator+(MyString& a, const MyString& b)
{
	int nLen1 = strlen(a.m_str);
	int nLen2 = strlen(b.m_str);

	char* tem = new char[nLen1+1];
	strcpy_s(tem, nLen1+1, a.m_str);

	delete[] a.m_str;

	a.m_str = new char[nLen1+nLen2+1];
	strcpy_s(a.m_str, strlen(tem)+1, tem);

	strcat_s(a.m_str, nLen1+nLen2+1, b.m_str);

	delete[] tem;
	return a.m_str;
}

ostream& operator<<(ostream& os, const MyString& str)
{
	os<<str.m_str;
	return os;
}

int _tmain(int argc, _TCHAR* argv[])
{
	MyString s1("Hi");
	MyString s2; 
 
	s2 = s1 + " there";

	cout<<s2<<endl;
	return 0;
}
If I comment out my implementation of assignment operator, then program will crash on the line of s2=s1+" there". I understand without assignment operator overloading, default assignment operator only does shallow copy. As the result, two pointers(m_str) will point to same address. But at the moment of calling s2 = s2 + " there", it looks like no pointer is deleted. So why does it crash there?
Also is there any improvement on my code? Thanks for your inputs.