构造函数调用已创建的对象
如果我在已经构造的对象或结构上调用构造函数, 它将分配新空间,还是仅使用现有空间?那么第一次对象分配是否更耗费资源呢?像这样:
struct F {
int a,b,c,d;
F(int _a, int _b) {a = _a; b = _b};
void a(int _a, int _b) {a = _a; b = _b};
};
//first constructor call
F f = F(5, 6);
//second constructor call on an already constructed object
f = F(7, 8);
//third constructor call on an already constructed object
f(7, 8);
//is the constructor call more res. intesive, than the call to a function which does the same?
f.a(9, 0)
构造函数调用是否比调用具有相同功能的函数(void a(...)
)更占用资源?
当我在已创建的对象上调用构造函数时,析构函数是否会被调用?
If I call a constructor on an already constructed object or struct,
will it allocate new space, or just use the existing space? So is the first object allocation more resource intensive? Like this:
struct F {
int a,b,c,d;
F(int _a, int _b) {a = _a; b = _b};
void a(int _a, int _b) {a = _a; b = _b};
};
//first constructor call
F f = F(5, 6);
//second constructor call on an already constructed object
f = F(7, 8);
//third constructor call on an already constructed object
f(7, 8);
//is the constructor call more res. intesive, than the call to a function which does the same?
f.a(9, 0)
Is the constructor call more resource intesive, than the call to a function which does the same (void a(...)
)?
Does the destructor gets called, when I call a constructor on an already created object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
首先,
[c]
标记不合适,因为构造函数是 C++ 独有的功能。我假设您提供的代码片段实际上是 C++,而不是 C 的某种奇怪的方言。C++ 和 C 是不同的语言;不要将您的问题标记为两者,因为每个问题都会得到不同的答案。其次,你的构造函数定义是错误的。构造函数必须与类本身具有完全相同的名称。所以OP 只是犯了一个拼写错误。f()
应该是F()
。是的,C++ 中区分大小写很重要!我假设这就是您对代码片段其余部分的意思。在我解释其余代码的作用之前,您必须了解所有C++ 中的类(和结构)具有编译器自动生成的特殊成员函数,如果您不要提供它们。也就是说,您的代码片段基本上与以下内容相同:
如果您没有定义复制构造函数、复制赋值运算符或析构函数,则编译器将为您生成它们。另外,如果您不提供其他构造函数,编译器将生成默认构造函数。类
F
没有默认构造函数,因为已经有一个接受两个参数的(非复制)构造函数。复制构造函数和复制赋值运算符的默认实现只是复制每个数据成员。
存在特殊成员函数的原因是因为 C++ 概括了将基本类型复制到用户定义对象的概念。考虑一下:
对于像 int 这样的基本类型,您可以像这样复制它的值。 C++ 将复制语义推广到对象,因此您可以执行以下操作:
现在您可以看到这如何应用于您的代码:
上面的行构造一个临时
F
对象,然后将临时对象复制到f< /code> 通过复制构造函数。然后临时
F
对象被破坏。上面的行构造了另一个临时
F
对象,然后通过复制赋值运算符将该临时对象分配给f
。然后临时F
对象被破坏。原始的f
对象没有被破坏。上面的行是对名为
f
的对象的正常函数调用。对于您的代码片段,假设编译器不会优化临时变量(实际上通常会这样做),那么调用函数
a
会“占用更少的资源”,因为在这种情况下不会生成临时变量。但是,对于您的第一次构造函数调用,您可以这样做:了解构造函数的用途:它们用于创建对象。如果你已经有一个对象,那么你不需要调用构造函数。
正如我多次推荐的那样,请挑选一本优秀的 C++ 书籍并阅读它。特殊成员函数及其作用对于 C++ 来说非常基础。
First off, the
[c]
tag is inappropriate since constructors are a C++-only feature. I'll assume the code snippet you provided is in fact C++ and not some weird dialect of C. C++ and C are different languages; do not tag your questions as both since you will get different answers for each.Second, your constructor definition is wrong. Constructors must have the exact same name as the class itself. SoOP simply made a typo.f()
should've beenF()
. Yes, case-sensitivity matters in C++! I'll assume this is what you meant for the rest of the code snippet.Before I explain what the rest of your code does, you must understand that all classes (and structs) in C++ have special member functions that are automatically generated by the compiler if you don't provide them. That is, your code snippet is basically the same as:
If you do not define a copy constructor, a copy assignment operator, or a destructor, the compiler will generate them for you. Also, if you don't provide some other constructor, the compiler will generate a default constructor. There is no default constructor for class
F
since there's already a (non-copy) constructor that accepts two arguments.The default implementation of the copy constructor and the copy assignment operator simply copies each data member.
The reason why special member functions exist is because C++ generalizes the notion of copying primitive types to user defined objects. Consider this:
With primitive types like
int
s, you can copy around its value just like that. C++ generalizes the copy semantics to objects so you can do this:Now you can see how this applies to your code:
The line above constructs a temporary
F
object, then copies the temporary intof
via the copy constructor. The temporaryF
object is then destructed.The line above constructs another temporary
F
object, then assigns the temporary intof
via the copy assignment operator. The temporaryF
object is then destructed. The originalf
object is not destructed.The line above is a normal function call on an object called
f
.For your code snippet, assuming compilers do not optimize away the temporaries (they in fact usually do), then calling the function
a
is "less resource intensive" since no temporaries are made in that case. However, for your first constructor call, you can just do this:Understand what constructors are used for: they are used to create objects. If you already have an object, then you don't need to call a constructor.
As I have recommended many times, please pick up a good C++ book and read it. Special member functions and what they do are quite fundamental to C++.
(在您发布的代码中,您在构造函数中使用了小写的 f 而不是大写的 F,我认为这是一个拼写错误)
您的问题很有趣,因为您提出的问题和您提出的代码写的都不一样。在代码中,您编写了
This does call F 构造函数,但不在现有的 f 对象上。相反,这会创建一个临时 F 对象,该对象通过调用以 7 和 8 作为参数的 tue 构造函数进行初始化,然后使用赋值运算符将现有的 f 变量设置为等于该新对象。因此,构造函数不会在对象上被调用两次;相反,这里调用的是分配。更一般地,如果您为现有对象分配新值,则将使用赋值运算符而不是构造函数来进行复制。这将重用对象的现有内存,尽管它可能会触发辅助内存分配和释放。
没有安全的方法可以两次调用对象的构造函数。如果您确实想调用已创建的对象的构造函数,则可以使用放置 new 来实现:
这是不安全的,因为它绕过了析构函数通常会执行的典型资源清理,并盲目地覆盖现有元素,因此这几乎是从未在实践中做过。我提到它主要是出于好奇和完整性。 :-)
(In the code you posted you've used a lower-case f instead of an upper-case F for the constructor, which I assume is a typo)
Your question is interesting because the question you've asked and the code you've written are not the same. In the code, you've written
This does call the F constructor, but not on the existing f object. Instead, this creates a temporary F object initialized by calling tue constructor with 7 and 8 as arguments, then uses the assignment operator to set the existing f variable equal to this new object. Consequently, the constructor is not invoked twice on the object; instead it's the assignment that gets called here. More generally, if you ever assign an existing object a new value, the assignment operator, not a constructor, will be used to do the copying. This will reuse the existing memory for the object, though it may trigger auxiliary memory allocations and deallocations.
There is no safe way to invoke an object's constructor twice. If you really do want to invoke the constructor of an object that's already been created, you can do so using placement new:
This is unsafe as it bypasses typical resource cleanup the destructors normally would do and blindly overrides the existing elements, so this is almost never done in practice. I mention it mostly for the sake of curiosity and for completeness. :-)
我忽略OP中的实现,直接进入QA:
吗?不会,该对象不会被重新分配。将调用构造函数的实现(例如函数调用)。
通常你不应该这样做,除非你正在实现一个集合(例如
vector
)。但是,回答这个问题:是的,第二个需要更少的指令。编译器生成简单的指令来设置分配(如果在堆栈上或其他地方)。所以自动创建对象确实有几个阶段,而您正在绕过其中的一些阶段。但认真地说:不要将此视为一种优化 - 仅在绝对必要时才手动调用构造函数/析构函数(再次考虑集合类型)。
潜在地,编译器的努力也会发挥作用。请记住,构造函数和析构函数调用层次结构中每个类的实现,因此...如果您的类层次结构不平凡,那么单个函数很可能会更快。
如果您以这种方式显式构造一个对象,那么答案是“不”。您的工作就是适当地配对显式调用。你不能错误地实施这个,它和 UB 一样好。顺序始终是
construct->destruct
。只是为了清楚所使用的语法:
i'm ignoring the implementation in the OP, and going straight to the QA:
no, the object will not be reallocated. the constructor's implementation will be called (e.g. a function call).
you should generally not do this, unless you're implementing a collection (e.g.
vector
).but, to answer the question: yes, the second will require fewer instructions. the compiler produces trivial instructions to set up the allocation (if on the stack or elsewhere). so there really is a few stages to creating an object automatically, and you are bypassing some of that. but seriously: don't consider this as an optimization -- only call the constructor/destructor manually if you absolutely must (again, think collection types).
potentially, the compiler's efforts also weigh in. remember, constructors and destructors call the implementation of each class in the hierarchy, so... it's quite likely that a singular function would be faster if your class hierarchy is non-trivial.
if you explicitly construct an object in this manner, then the answer is 'no'. it's your job to appropriately pair the explicit invocations. you cannot afford to implement this incorrectly, it's as good as UB. the order is always
construct->destruct
.just to be clear of the syntax used:
您的程序中存在语法错误,修改您的代码
片段 - 当构造的对象超出范围时(即,当对象的生命周期完成时),析构函数被调用。
There are syntatic mistakes in your program, modifying your snippet-
Destructor gets called, when the constructed object goes out of scope ( ie., when the life time of the object completes).
你的类 F 没有构造函数,只有方法 f。因此,任何时候都不会调用构造函数。
Your class F does not have a constructor but only a method f. So, no constructor is called at any time.