我的理解是,当你制作一个定义指针变量的类的拷贝时,拷贝指针,但是指针指向的数据不是。C++类拷贝(指针拷贝)
我的问题是:是否假设在这种情况下的“指针副本”只是实例化一个新的指针(动态内存分配)相同类型?例如,新指针只是一个包含任意内存地址的新分配,并且应该注意将该新指针指向适当的内存地址?
我认为对这个问题有一个相当简单的答案,我为它的微不足道的本性表示歉意,但我试图在更深层次上理解指针,并且这出现在我在互联网上的研究指针上。
问候,
乍得
我的理解是,当你制作一个定义指针变量的类的拷贝时,拷贝指针,但是指针指向的数据不是。C++类拷贝(指针拷贝)
我的问题是:是否假设在这种情况下的“指针副本”只是实例化一个新的指针(动态内存分配)相同类型?例如,新指针只是一个包含任意内存地址的新分配,并且应该注意将该新指针指向适当的内存地址?
我认为对这个问题有一个相当简单的答案,我为它的微不足道的本性表示歉意,但我试图在更深层次上理解指针,并且这出现在我在互联网上的研究指针上。
问候,
乍得
的指针将被简单地复制作为一种价值 - 所以这两个类将指向相同的原始记忆,没有新的分配发生。 浅拷贝 - 这是默认情况下的语言。
如果您需要分配新内存并复制数据,您必须自己在复制构造函数中执行该操作。 深拷贝 - 你必须自己做这个
编辑:这是C++的优点之一,你可以自由决定如何复制工作。它可能是只有读取访问内存的对象的副本可以避免复制内存的成本。如果新对象需要写入,您也可以实现只复制原始数据的类。
@Chad Kemp:另请参阅`boost :: shared_ptr`和*智能指针*。还研究*浅拷贝*和*深拷贝*之间的区别。 – 2011-02-17 19:12:17
复制的指针将指向完全相同的地址。没有新的分配。
是的,指针只是包含内存地址,如果你想做一个更深的副本,你需要自己编写代码,在复制构造函数中。
如果您始终通过同一类的指针引用同一类型的数据,并且需要将数据与对象一起复制,那么您也可以考虑将它只作为普通成员,而不是指针。
首先,类中的指针是静态的(即编译器知道这个类中有一个指针,它的大小是多少,所以当类被实例化时不需要动态内存分配)。
如果您复制类(并且没有定义特殊的复制构造函数),那么新类中的指针将指向与旧类中指针相同的内存位置。为了澄清:
#include <iostream>
class A {
public:
int *p;
};
int main() {
A a,b;
a.p = new int(10);
b = a;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10
*(b.p) = 3;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 3
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3
return 0;
}
现在如果你想在复印时,你需要写一个拷贝构造函数和拷贝赋值构造函数来分配新的内存:
#include <iostream>
class A {
public:
int *p;
A() : p(0) {}
A(const A& other) { // copy constructor
p = new int(*other.p);
}
A& operator=(const A& other) { // copy assignment constructor
// protect against self assignment
if (this != &other) {
if (p != 0) {
*p = *other.p;
} else { // p is null - no memory allocated yet
p = new int(*other.p);
}
}
return *this;
}
~A() { // destructor
delete p;
}
};
int main() {
A a,b;
a.p = new int(10);
b = a;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 10
*(b.p) = 3;
std::cout << "*(a.p) = " << *(a.p) << std::endl; // 10
std::cout << "*(b.p) = " << *(b.p) << std::endl; // 3
return 0;
}
当你这样做,你也应该写一个析构函数(见Rule of three),因为如果类被破坏,在复制/复制分配构造函数中分配的内存需要取消分配:
指针不会实例化动态内存分配。指针和分配是完全不同的东西。
如果您复制指向动态分配的内存的指针,则会有两个指针指向相同的分配内存。既然你已经复制它,它已经指向了内存块。具体来说,如果使用编译器生成的拷贝构造函数,新指针将指向与旧指针完全相同的内容。如果没关系,你不需要做任何事情。
您确实存在何时释放内存的问题。释放它两次通常会导致堆腐败,这是讨厌的。不释放它会导致内存泄漏,在某些情况下这可能是可以接受的。在另一个指针通过之前释放它也会导致问题。出于这个原因,有多个指向相同内存的人经常进入Boost项目,并使用他们的shared_ptr模板(这将在即将出现的新标准中出现,并且存在于大多数最新的系统中)。
如果您希望每个指针指向单独的内存块,您必须通过编写自己的拷贝构造函数来设置它,并分配一个新块并在其中复制必要的数据。 (出于完全相同的原因,您还需要编写自己的赋值运算符,以及您自己的析构函数,以便释放内存。有一条经验法则,称为三条法则,即如果您需要编写自己的副本构造函数,赋值运算符或析构函数,您可能需要编写它们全部)。
指针和它们指向的数据是分开的。马丁的答案应该澄清如果不检查基本知识:http://www.cplusplus.com/doc/tutorial/pointers/ – AJG85 2011-02-17 19:01:00