简单的C/C++结构体,一般就定义数据成员,而已,如:
struct S_Book
{
CString csName;
CString csAuthor;
float fPrice;
short int nVersion;
};
这熟悉的代码在很多程序里面都能看到,因为很多程序员都是这样写的。那么,有问题吗?一般场景没有问题,然而对应稍微复杂些的场景,就不够用了,甚至能让程序崩溃。比如,它不能直接赋值,它没有拷贝构造函数,如果数据成员有指针,呵呵。。那么,结构体正确的标配是怎样的呢,没有统一答案,不过,根据本人经验,至少包括构造函数、初始化函数、拷贝构造函数和赋值函数吧,如下是“标配”,至于是否需要重载加减乘除等,那是特殊情况了。
那么,下面的“标配”,代码有问题吗?
struct S_Book
{
CString csName;
CString csAuthor;
float fPrice;
short int nVersion;
S_Book()
{
Init();
}
void Init()
{
csName.Empty();
csAuthor.Empty();
fPrice = 999999;
nVersion = 9999;
}
S_Book(const S_Book& stItem)
{
csName = stItem.csName;
csAuthor = stItem.csAuthor;
fPrice = stItem.fPrice;
nVersion = stItem.nVersion;
}
S_Book& operator= (const S_Book& stItem)
{
if(this == &stItem)
{
return *this;
}
memset(this,0,sizeof(S_Book));
memcpy(this,&stItem,sizeof(S_Book));
return *this;
}
};
答案是 有的。在release版本不提示问题,但是在debug时,出现_CtrIsValidHeapPointer(pUserData)错误。为什么呢,如果把CString类型的数据成员删除掉,就不会出现这个问题。原因是CString类型内部有释放内存机制,内存操作函数操作内存时,出现了错误,所以解决方法就知道是什么了。
那么,C/C++结构体的正确打开方式:
struct S_Book
{
CString csName;
CString csAuthor;
float fPrice;
short int nVersion;
S_Book()
{
Init();
}
void Init()
{
csName.Empty();
csAuthor.Empty();
fPrice = 999999;
nVersion = 9999;
}
S_Book(const S_Book& stItem)
{
csName = stItem.csName;
csAuthor = stItem.csAuthor;
fPrice = stItem.fPrice;
nVersion = stItem.nVersion;
}
S_Book& operator= (const S_Book& stItem)
{
if(this == &stItem)
{
return *this;
}
//memset(this,0,sizeof(S_Book));
//memcpy(this,&stItem,sizeof(S_Book));
csName = stItem.csName;
csAuthor = stItem.csAuthor;
fPrice = stItem.fPrice;
nVersion = stItem.nVersion;
return *this;
}
};
基本的结构体能“规范”使用,就再也不用担心更复杂的结构体了。
struct S_Book
{
CString csName;
CString csAuthor;
float fPrice;
short int nVersion;
S_Book()
{
Init();
}
void Init()
{
csName.Empty();
csAuthor.Empty();
fPrice = 999999;
nVersion = 9999;
}
S_Book(const S_Book& stItem)
{
csName = stItem.csName;
csAuthor = stItem.csAuthor;
fPrice = stItem.fPrice;
nVersion = stItem.nVersion;
}
S_Book& operator= (const S_Book& stItem)
{
if(this == &stItem)
{
return *this;
}
//memset(this,0,sizeof(S_Book));
//memcpy(this,&stItem,sizeof(S_Book));
csName = stItem.csName;
csAuthor = stItem.csAuthor;
fPrice = stItem.fPrice;
nVersion = stItem.nVersion;
return *this;
}
};
typedef CArray<S_Book,S_Book&>astBook;
struct S_BookInfo
{
int iNo;
CString csAddr;
astBook astBooks;
S_BookInfo()
{
Init();
}
void Init()
{
iNo = 999999999;
csAddr.Empty();
astBooks.RemoveAll();
}
S_BookInfo(const S_BookInfo& stItem)
{
iNo = stItem.iNo;
csAddr = stItem.csAddr;
astBooks.Copy(stItem.astBooks);
}
S_BookInfo& operator= (const S_BookInfo& stItem)
{
if(this == &stItem)
{
return *this;
}
iNo = stItem.iNo;
csAddr = stItem.csAddr;
astBooks.Copy(stItem.astBooks);
return *this;
}
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
astBook astBookAll;
S_Book S_Book1;
S_Book1.csAuthor = "Gorden";
S_Book1.csName = "Easy Python";
S_Book1.fPrice = 86.9f;
S_Book1.nVersion = 3;
cout << "******************** S_Book1 ********************" << endl;
cout << "Book's Name:" << (LPCTSTR)S_Book1.csName << endl;
cout << "Author:" << (LPCTSTR)S_Book1.csAuthor << endl;
cout << "Price:" << S_Book1.fPrice << endl;
cout << "Version:" << S_Book1.nVersion << endl;
astBookAll.Add(S_Book1);
S_Book S_Book2;
S_Book2 = S_Book1;
S_Book2.nVersion = 4;
cout << "******************** S_Book2 ********************" << endl;
cout << "Book's Name:" << (LPCTSTR)S_Book2.csName << endl;
cout << "Author:" << (LPCTSTR)S_Book2.csAuthor << endl;
cout << "Price:" << S_Book2.fPrice << endl;
cout << "Version:" << S_Book2.nVersion << endl;
astBookAll.Add(S_Book2);
S_Book S_Book3;
S_Book3.csAuthor = "Gorden";
S_Book3.csName = "Easy C++";
S_Book3.fPrice = 99.8f;
S_Book3.nVersion = 7;
cout << "******************** S_Book3 ********************" << endl;
cout << "Book's Name:" << (LPCTSTR)S_Book3.csName << endl;
cout << "Author:" << (LPCTSTR)S_Book3.csAuthor << endl;
cout << "Price:" << S_Book3.fPrice << endl;
cout << "Version:" << S_Book3.nVersion << endl;
astBookAll.Add(S_Book3);
S_BookInfo S_BookInfos;
S_BookInfos.iNo = 1;
S_BookInfos.csAddr = "http://book.dangdang.com";
S_BookInfos.astBooks.Copy(astBookAll);
cout << "************************ S_BookInfos ************************" << endl;
cout << "No:" << S_BookInfos.iNo << endl;
cout << "Addr:" << (LPCTSTR)S_BookInfos.csAddr << endl;
for(int i = 0; i < S_BookInfos.astBooks.GetSize(); i++)
{
cout <<"========================" << "astBooks" << "[" << i << "]:" << endl;
cout << "Book's Name:" << (LPCTSTR)S_BookInfos.astBooks[i].csName << endl;
cout << "Author:" << (LPCTSTR)S_BookInfos.astBooks[i].csAuthor << endl;
cout << "Price:" << S_BookInfos.astBooks[i].fPrice << endl;
cout << "Version:" << S_BookInfos.astBooks[i].nVersion << endl;
}
cout << "************************ S_BookInfos ************************" << endl;
}
return nRetCode;
}