2011-04-22 104 views
0
template <class T> 
class ListNode { 

public: 
    T* data; 
     ListNode<T>* next; 
} 

可以说我有一个列表节点模板,并在代码中的某处我想获取数据的副本 - 意味着不是指向数据(T *)的指针的副本,而是一个新的指针(T *),它将指向存储器中具有相同信息的另一个地方。C++模板问题

如何在使用C++模板时执行此操作?我怎样才能复制(*数据),如果我不知道什么是

+3

当你知道类型时,你如何做到这一点?它适用于模板类型。 – 2011-04-22 14:12:38

+1

您*知道类型...'T' – 2011-04-22 14:13:42

+0

@Konrad:或者,它同样不适用于非模板。到目前为止所有的答案都会导致切片。 – 2011-04-22 14:28:32

回答

0

T有要被复制施工的,这样就可以做

template <class T> 
    ListNode<T>::ListNode(const ListNode<T>& src) 
    { 

     ... 
     // given a preexisting copy, src, create a new T to 
     // perform a copy 
     T* destT = new T(*srcT); 
    } 

T的类型。如果T有一个拷贝构造函数,这将起作用。如果没有,编译器会给你一个错误(可能是一个非常神秘的错误)

+0

NM ...它涉及咖啡,它不是你的最终目的。 – 2011-04-22 14:21:27

+0

为什么编译器应该给出错误; 编译器不会生成默认的拷贝构造函数吗? – iammilind 2011-04-22 14:29:11

0

使用运算符=或复制构造函数。这是标准做法,它们都会生成对象的副本。

因此,举例来说:

T *p = other_pointer; 
*p = *data; 

或者

T* copy = new T(*data); 
+1

适用于允许切片的“生成副本”的值。 – 2011-04-22 14:31:25

+0

@本:没有标准的虚拟复制功能,所以你拿你可以得到的。 – 2011-04-22 17:24:10

0

当创建一个模板类型的副本,实际上你不用担心的类型,例如,住该任务上的副本构造函数或该类型的赋值运算符:

template <class T> 
class ListNode { 
public: 
    T* data; 
    ListNode<T>* next; 
    T* getCopy() { new T(*data); } // get copy of "data" 
}; 

假设您使用此ListNode<T>class A,那么你可以有在定义(和赋值运算符以及)拷贝构造函数:

class A { 
public: 
    A(const A& copy); 
}; 

现在,当ListNode<T>::getCopy()被调用时,它会调用的内部拷贝构造函数。

+0

-1:每次有人要求复制时,潜在的内存泄漏可能不是一个好设计......将其包装在智能指针中,或者最好提供显式拷贝构造函数和/或赋值运算符。 – AJG85 2011-04-22 15:02:42

+0

@ AJG85,我不这么认为是内存泄漏。提问者询问'T *'的副本,它可以存储在其他对象的'data'成员中,并且可以在析构函数中被删除。 – iammilind 2011-04-23 04:40:33

+0

您返回一个像这样的副本:'T getCopy()const {* data; }'你正在做的是在堆上分配内存并在一个** public **方法中返回一个指向它的指针,这很容易导致内存泄漏和孤儿指针......调用你的方法的任何人都必须存储指针并调用delete '以避免内存泄漏,没有例外。 – AJG85 2011-04-25 15:47:27

1

编译器知道T的类型。不知道的是指向多少个实例T。在获得实际的实现方面,简短的答案是不要使用指针类型。改用容器。由于无论如何您都在复制节点数据,所以开销很小。下面明显的例子:

template <class T> 
class ListNode { 
public: 
    // use a vector as the container 
    std::vector<T> data; 
    ListNode<T>* next; 
    // initializer from pointer primitive 
    ListNode(const T* ps,size_t elements) 
    { 
     data.assign(ps,ps+elements); 
    } 
    // copy templated instance 
    ListNode(const ListNode& arg) 
    { 
     data = arg.data; 
    } 
    // assignment 
    ListNode& operator=(const ListNode& arg) 
    { 
     if (this != &arg) 
     { 
      data = arg.data; 
     } 
     return *this; 
    } 
}; 

实际使用量将与此类似:

{ 
    const char* ps = "Hello World"; 
    ListNode<char> ln1(ps,strlen(ps)); 
    ListNode<char> ln2 = ln1; 
} 

你可以,当然,变得更加复杂,解决方案,但他们都将涉及保留的实例数的轨道键入指针指向的T

+0

+1:尽管范例的范围仍然是一个简单的选择,简单是好的。 – AJG85 2011-04-22 15:16:09