C++;构造问题 在C++初学者的第二版程序中,有以下语句: HeapPoint::HeapPoint(int x, int y): thePoint(new Point(x,y)) { }
这等于:C++;构造问题 在C++初学者的第二版程序中,有以下语句: HeapPoint::HeapPoint(int x, int y): thePoint(new Point(x,y)) { },c++,pointers,multiple-constructors,C++,Pointers,Multiple Constructors,这等于: HeapPoint::HeapPoint(int x, int y) { thePoint = new Point(x,y); } 既然我们在构造函数中这样做,那么为x和y分配的值是什么?我们是否应该在新点(x,y)中写入值而不是x和y?或者,这样做是正确的 更新:我想我想到了初始化x和y,因为在书中它有以下功能: HeapPoint myHeapPoint(2,4); 假设点是一个原始指针,那么无论出于何种目的,它都是相同的。第一个版本初始化点,而第二个版本为点,但效果几乎总是一
HeapPoint::HeapPoint(int x, int y) { thePoint = new Point(x,y); }
既然我们在构造函数中这样做,那么为x
和y
分配的值是什么?我们是否应该在新点(x,y)
中写入值而不是x
和y
?或者,这样做是正确的
更新:我想我想到了初始化x
和y
,因为在书中它有以下功能:
HeapPoint myHeapPoint(2,4);
假设
点
是一个原始指针,那么无论出于何种目的,它都是相同的。第一个版本初始化点,而第二个版本为点,但效果几乎总是一样的,甚至可以生成完全相同的机器代码
他们什么时候不一样了
点
是某种智能指针,第一种形式将通过将新点传递给其构造函数来初始化它,而第二种形式可能会将其初始化为零,然后将新点传递给赋值运算符归根结底,这是一个风格和一致性的问题,因此我更喜欢初始形式而不是作业形式。第一种形式与第二种形式不同 在这种特殊情况下,它们可能会产生相同的结果。然而,Point可以很容易地为
新点
实现赋值运算符,并做一些“不同的事情”(我没有这本书,所以我不知道每个细节)。同样,赋值操作符应该做您期望的事情。。。但是,点可以是一个容器(例如,智能指针),当使用初始化(点)
vs默认初始化,然后使用赋值时(出于某些奇怪的原因),该容器的行为可能会有所不同
在这种情况下,这些细节可能无关紧要,但它们确实会影响初始化顺序和执行。当您的程序增长时,差异将非常重要。此时,初始化需要时间,您需要确保对象被正确初始化:它们被正确构造(第一次)并且以正确的顺序构造。最明显的情况是:当默认构造函数的行为与带有参数的构造函数的行为不同时,尤其是当构造函数生成分配或具有其他耗时(或行为不同)的副作用时,会产生不同
既然我们在构造函数中这样做,那么为int x和int y分配的值是什么
这完全取决于点的构造函数
我们应该在新的点(x,y)中写入代替x和y的值吗?或者,这样做是正确的
(对于大多数团队)首选的方法是尽可能使用初始化列表和正式构造函数,并编写类型以支持正确的初始化。当代码库增长时,会出现很多微妙之处。此构造函数使用初始化列表:
HeapPoint::HeapPoint(intx,inty):点(新点(x,y)){}
如果您希望这样声明点,则在假设情况下可能需要正确初始化:
常数点*常数点代码>
第一个const
表示您不能修改点(例如Point.x
或Point.y
)。第二个常量表示不能为变量分配新的分配。OP中的示例非常简单,但随着程序的增长肯定会有所帮助。通常,您应该更喜欢第一个构造,即使用初始化器列表
第二种结构更可取,如果
你想试一下…抓住它还是
您有几个这样的消息,并将它们存储为常规指针,在这种情况下,您需要注意其中一条消息可能会失败,您需要进行一些清理。您可以使用某种自动/唯一的方法来处理这个问题,直到您知道所有分配都成功了,然后继续释放它们。这是因为您可能会在析构函数中删除它们,但如果构造函数抛出,则不会调用析构函数
两者都是一样的。第一种情况:
HeapPoint::HeapPoint(int x, int y): thePoint(new Point(x,y)) { }
使用点
所属的类的构造函数,并使其指向为点
分配的新内存
第二种情况也分配了内存,其地址分配给点
这两种形式并不完全相同,因为初始化列表给出了一个直接放入变量的值,而如果合适的话,变量是默认初始化的(例如,std::字符串默认为空,但int、double等成员变量具有有效的随机值),然后在遇到赋值操作时进行覆盖。这种覆盖可能效率较低,但对于某些常量和引用成员变量来说也是非法的,这些变量在创建后不允许更改。通常,只要有可能,就使用初始化器列表,这样做不会出错。只有当您发现不要初始化某些内容,因为如果在构造函数体中放入显式赋值语句,则需要先执行一些其他步骤。请注意初始化是按顺序进行的
class A
{
public:
B& _b;
C& _c;
A(B& b, C& c):_b(b), _c(c) // compiles !
{
}
A(B& b, C& c)
{
_b(b); // does not compile !
_c(c); // does not compile !
}
}