2012-10-07 34 views
1

我用一个模板定义了一个类,该模板定义了一个通用数组类型T个元素N.我有另一个有这个数组实例作为成员的类。当我尝试使用setString函数时,我传递的数组从任意的15个元素到4个元素。作为参数传递给C++类时的内存丢失

// testClassArraySize.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <stdio.h> 
#include <iostream> 
#include <istream> 
#include <ostream> 
using namespace std; 

template<class T, int N> 
class CArray { 
public: 
    T arr[N]; 
    CArray(void) {/*arr=(T *)malloc(sizeof(T)*N);*/ 
     if (arr == NULL) { 
      cout << "allocation error\n"; 
     } 
    } 
    ; 
    //CArray (int n) {arr=new T [n]; if(arr==NULL){exit(0); cout<<"allocation error\n";}}; 
    CArray operator=(const T *); 
    T operator[](const int i) { 
     return arr[i]; 
    } 
    ; 
}; 

template<class T, int N> 
CArray<T, N> CArray<T, N>::operator=(const T *srce) { 
    size_t x = sizeof(arr); 
    size_t y = sizeof(srce); 
    for (int j = 0; j < sizeof(arr); j++) { 
     if (j > sizeof(srce)) { 
      arr[j] = 0; 
      break; 
     } 
     arr[j] = srce[j]; 
    } 
    return *this; 
} 

class myTestClass { 
private: 
    CArray<char, 15> myString; 
public: 
    myTestClass setString(char set[15]) { 
     myString = set; 
     size_t x = sizeof(set); 
     return *this; 
    } 
    ; 
}; 

int main() { 
    myTestClass myObject; 
    myObject.setString("helloWorld"); 
    return 0; 
} 

有没有人有任何想法为什么?

+1

当然,您还没有启用任何编译器警告,是吗?这些可以非常有帮助。 –

+0

为这个想法+1,但MSVC10没有任何。你期望哪一个? – dyp

回答

2

这有几个问题,但一个你可能会看到的是线

CArray<T, N> CArray<T, N>::operator= (const T *srce) 

注:const T* source是一个指针,因此sizeof(srce)是指针的大小。我猜你正在使用32位系统?

sizeof为您提供了对象的大小(即“存储区域”)。对于数组,这是整个数组的大小(以字节为单位)。 sizeof(int[10]) == sizeof(int) * 10。指针本身就是一个对象,其大小取决于C++实现(OS,编译器等)。在32位系统上,它通常是4个字节。因此sizeof(char*)是4字节,则传递给函数数组的不是长度,也就是仍然sizeof((char*)(char[10]))是4字节,而不是10

可能看到的另一个问题(而是仅由调试/跟踪)是setString(char set[15])是解决为setString(char* set)。因此x = sizeof(set)解析为x = sizeof(char*)其通常4.

传递“HelloWorld”的到setString,它期待一个 15项字符数组 char*;我会说这不是一个好主意,因为“helloWorld”的类型为char const[10](请注意const)。 采用15个字符数组的正确语法是char (&set)[15]

如果添加像一个模板成员函数可以做到这一点更优雅:

// in class CArray 
template < std::size_t length > 
CArray& operator= (const T (&srce)[length]); // note I return a reference, so no copying 

这样一来,你会得到数组的大小作为一个模板参数。注意:因为我在作业中使用了const T,所以还需要在setString中强制执行const。

template < class T, int N > 
template < std::size_t srce_length > 
CArray < T, N >& CArray < T, N > :: operator= (const T (&srce)[srce_length]) 
{ 
    for (int j = 0; j < N; j++) { // N is the own length 
     if (j >= srce_length) { // note the >= instead of >, and srce_length instead of sizeof 
      arr[j] = 0; 
      break; 
     } 
     arr[j] = srce[j]; 
    } 
    return *this; 
} 
+0

谢谢。但是当我将数组传递给setString时,甚至在我调用CArray operator =(const T * srce)之前,内存仍然丢失......但是,请尝试此解决方案。 – bathtub

+0

正如我所提到的,尝试将'setString'的签名更改为'char const(&set)[15]'。 – dyp

+0

好的,谢谢。这有助于。我不明白是什么把地址运算符作为参数或返回值不过。 – bathtub

相关问题