我正在尝试自学C ++,而且我再一次陷入困境,似乎无法修复它。 请原谅你即将看到的代码的可怕混乱。这也是我在这个网站上的第一篇文章,所以帖子的格式可能也会关闭,抱歉。
有两个文件:main.cpp和vect1.h (没有vect1.cpp,因为它似乎模板只能挂在头文件中)
main.cpp中:
#include <iostream>
#include "vect1.H"
using namespace std;
int main(){
vect1<int> inst1(10);
inst1[9]=4;
cout<<inst1[9]<<endl;
//-----
vect1<double> inst2(10);
inst2[5]=5.112;
cout<<inst2[5]<<endl;
//-----
//====PART 2=====//
cout<<"--------"<<endl;
inst2[9]=999;
cout<<inst2[9]<<endl;
//inst2.pop();
inst2.push(2);
cout<<inst2[9]<<endl;
cout<<inst2[10]<<endl;//New block
system("PAUSE");
return 0;}
vect1.h:
#ifndef VECT1_H
#define VECT1_H
#include <iostream> //DEBUG
template <class T>
class vect1{
private:
T *ptr;
T total; //work on this
int units;
int counter;
public:
//vect1();
vect1(T);
vect1();
T &operator[](const int &);
void pop();
void push(T);
};
//---------------------
/*
template <class T>
vect1<T>::vect1(){
ptr = new int [0];
}
*/
template <class T>
vect1<T>::vect1(T number){
ptr = new T [number];
total=0;
units=(int)number;
for(counter=0;counter<number;counter++){
ptr[counter]=0;
}
}
/* now the destruct is giving me errors...
template <class T>
vect1<T>::~vect1(){
total=0;
delete[] ptr;
}*/ //<<this line tosses a C2039 error
template <class T>
T &vect1<T>::operator[](const int & ref){
if(ref>0 && ref<(units)){
return ptr[ref];
}else{
throw "Error! Out of range!"; //<<make catch
}
}
//--------
template <class T>
void vect1<T>::pop(){
units = (units-1);
T *tempPtr;
tempPtr = new T[units];
for(counter=0;counter<units;counter++){
tempPtr[counter]=ptr[counter];
}
delete[] ptr;
ptr = new T[units];
for(counter=0;counter<units;counter++){
ptr[counter]=tempPtr[counter];
}
delete[] tempPtr;
}
//--
template <class T>
void vect1<T>::push(T pushnum){
units++;
const int newsize=(int)units; //<<<<<
T *tempPtr;
tempPtr = new T[units];
for(counter=0;counter<(units-1);counter++){
tempPtr[counter]=ptr[counter];
}
//tempPtr[(int)units]=pushnum;
delete[] ptr;
std::cout<<units<<std::endl;//<<DEBUG
ptr = new T[units];
for(counter=0;counter<(units-1);counter++){
ptr[counter]=tempPtr[counter];
//ptr[9]=101;
}
ptr[newsize]=pushnum; /* <<bleh */
//ptr[newsize]=12321; //DEBUG //<<Even this isn't working...
delete[] tempPtr;
}
//---------------------
#endif
输出(在控制台中):
4
5.112
--------
999
11
999
-6.27744e+066
Press any key to continue . . .
计划就是当你弹出()它会创建一个新的临时数组T并复制除原始数据的最后一个块到临时数组,删除原始数组,然后创建一个新数组一个小于之前的尺寸并将所有内容发回,删除临时数组。推(数字)的想法相同,只是相反。 Push会将自身复制到temp,push会自行删除,然后重新创建自己的大小为1,然后将所有内容从temp发送到push并删除temp。然后将push发送的号码发送到新块。所以这个程序应该在第二个“999”行之后打印出'2'。但相反,我得到“-6.27744e + 066”。
Pop()似乎有效。八九不离十。但是有push(num)的真正问题。我似乎突然从我的析构函数中得到了C2039错误。它之前没有这样做,我还没有改变它。
我真的很感激,如果有人可以看看这个烂摊子,并给我一些关于修复的提示。谢谢!
我使用Visual Studio 2010作为我的编译器。
这是我的构建日志(包含一些很好的错误/警告!):
1>------ Rebuild All started: Project: chapter 16-5, Configuration: Debug Win32 ------
1>Build started 2/9/2012 5:34:01 PM.
1>_PrepareForClean:
1> Deleting file "Debug\chapter 16-5.lastbuildstate".
1>InitializeBuildStatus:
1> Creating "Debug\chapter 16-5.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1> main.cpp
1>e:\programming(cpp)\chapter 16-5\chapter 16-5\vect1.h(31): warning C4244: 'initializing' : conversion from 'double' to 'unsigned int', possible loss of data
1> e:\programming(cpp)\chapter 16-5\chapter 16-5\vect1.h(30) : while compiling class template member function 'vect1<T>::vect1(T)'
1> with
1> [
1> T=double
1> ]
1> e:\programming(cpp)\chapter 16-5\chapter 16-5\main.cpp(11) : see reference to class template instantiation 'vect1<T>' being compiled
1> with
1> [
1> T=double
1> ]
1>Manifest:
1> Deleting file "Debug\chapter 16-5.exe.embed.manifest".
1>LinkEmbedManifest:
1> chapter 16-5.vcxproj -> E:\Programming(CPP)\chapter 16-5\Debug\chapter 16-5.exe
1>FinalizeBuildStatus:
1> Deleting file "Debug\chapter 16-5.unsuccessfulbuild".
1> Touching "Debug\chapter 16-5.lastbuildstate".
1>
1>Build succeeded.
1>
1>Time Elapsed 00:00:10.62
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
答案 0 :(得分:1)
template <class T>
vect1<T>::vect1(T number){
ptr = new T [number];
total=0;
units=(int)number;
for(counter=0; counter<number; counter++) {
ptr[counter]=0;
}
}
此构造函数为number
个对象分配空间,但number
具有常规类型T
,并将其强制转换为int
。如果您想要一个字符串或对象的向量,转换为int失败。 number
应该有int类型。通常不需要进行转换,这可能是设计不良的一个症状(继承 - dynamic_cast除外)。
因为T
可能是任何东西,你无法在构造函数中初始化它,你必须将它留给向量的用户。
T &vect1<T>::operator[](const int & ref){
你使用const引用因为你可能被告知它比传递值更快。对于较大的对象,这适用于int,而不适用于int。引用基本上只是另一个指针(具有不同的语法)。该函数将地址传递给目标变量。指针和int通常都相同,因此这里没有任何改进,通过指针访问肯定比直接访问该值慢。
template <class T>
void vect1<T>::pop(){
units = units-1;
T *tempPtr = new T[units];
for(counter=0;counter<units;counter++){
tempPtr[counter]=ptr[counter];
}
delete[] ptr;
ptr = tempPtr;
}
无需将数据复制回ptr
即可复制指针。
template <class T>
void vect1<T>::push(T pushnum){
units++;
T *tempPtr = new T[units];
for(counter=0;counter<(units-1);counter++){
tempPtr[counter]=ptr[counter];
}
tempPtr[units-1]=pushnum; // New item is at units-1 position!
delete[] ptr;
ptr=tempPtr; // Again, just assign the pointer.
}
添加析构函数释放已分配的内存。
我希望这会有所帮助,我很抱歉我的英语不好。
答案 1 :(得分:0)
我发现的直接问题是:
const int newsize=(int)units;
ptr = new T[units];
...
ptr[newsize]=pushnum;
也就是说,您分配了newsize
个对象,但在这里您正在访问超出范围的值:只有索引0
... newsize - 1
可用。这也意味着您可能错过了初始化索引newsize - 1
的值,这可能会导致您引用的值。
也就是说,在查看代码时我注意到了一些事情:
push()
函数中多次分配内存!只需创建一个足够大的数组,复制内容并将其放置到位。在可调整大小的向量的实际实现中,您将过度分配空间,并在此内存耗尽时仅分配新内存。重新分配时,您将使用大于1的因子(例如1.5或2)来确保不经常重新分配。