我有一些类A
,我可以不使用任何东西构建它,也可以使用std::function
。在销毁时,应该调用给定的函数(如果有)。我的问题是,该对象在创建后立即被销毁,并由我的getSomeA()
函数返回,该函数在应该调用它之前调用std::function
。传递给构造函数的函数只能调用一次。一些示例代码:
#include <iostream>
#include <functional>
static void testFunction(const std::string& msg)
{
std::cout << "TestFunction: " << msg << "\n";
}
class A {
public:
A(void) = default;
A(const std::function<void()>& onDestroy) :
onDestroy(onDestroy)
{ }
~A(void)
{
if (onDestroy) onDestroy();
else std::cout << "in dtor but no onDestroy was set\n";
}
private:
std::function<void()> onDestroy;
};
A getSomeA(void)
{
return A(std::bind(testFunction, "the A that was created inside getSomeA"));
}
int main(void)
{
A b1;
std::cout << "After creating b1\n";
b1 = getSomeA();
std::cout << "After reassigning b1\n";
std::cout << "Here the program works with b1...\n";
}
程序输出
After creating b1
TestFunction: the A that was created inside getSomeA
After reassigning b1
Here the program works with b1...
TestFunction: the A that was created inside getSomeA
因此,函数在被调用之前被调用(在int main()的末尾)。
添加移动构造函数和赋值操作符后,一切都按预期工作:
A(A&& other) :
onDestroy(std::exchange(other.onDestroy, nullptr))
{ }
A& operator=(A&& other)
{
onDestroy = std::exchange(other.onDestroy, nullptr);
return *this;
}
以及程序输出
After creating b1
in dtor but no onDestroy was set
After reassigning b1
Here the program works with b1...
TestFunction: the A that was created inside getSomeA
实际问题:第一次销毁对象以便调用testFunction的位置是哪里?在getphaA()
中,或者在赋值之前但在getphaA()
中创建对象之后的main函数中?
所有的编辑:我试着把我的问题放下一个小时,但是因为我不知道在C语言中移动/复制语义学,这对我来说很难。
在第一个版本中,作为返回在getSomeA
中构造的对象的一部分,对象第一次被销毁。它的return
语句有效地构造了一个临时对象,然后将其分配给main
的b1
。如果忽略从函数返回的过程,则事件顺序为:
A <temporary object>(std::bind( ... )
b1=<temporary object>
<temporary object gets destroyed>
此时,由于临时对象被销毁,绑定函数被调用。临时对象是一个完全被欺骗的对象,其所有权利和特权都被授予。包括一个析构函数。
但是等等,还有更多!b1
是原始对象的完美逐位副本,带有绑定函数,然后被销毁。因此,当b1
被销毁时,该函数会再次被调用。
这是三位一体规则的间接结果。当一个对象拥有一个资源,并且必须保持对该资源的独占所有权时,您需要提供一个复制和/或移动构造函数和赋值运算符,以准确说明在这种情况下应该发生什么。
注:这些规则随着C17的保证副本省略而略有变化,但基本概念仍然是一样的。
基本问题:程序何时在C中调用类的析构函数方法?有人告诉我,每当对象超出范围或受到时都会调用它 更具体的问题: 1)如果对象是通过指针创建的,并且该指针后来被删除或给定一个新的地址来指向,它所指向的对象是否调用其析构函数(假设没有其他东西指向它)? 2) 接下来是问题1,什么定义了对象何时超出范围(与对象何时离开给定的{block}无关)。换句话说,什么时候对链表中的对象调用析构函数? 3) 你想手
我有这个代码,输出如下: 链接到下面的示例https://godbolt.org/z/z8Pn9GsTv 输出: 但交换析构函数的位置会产生其他结果: 代码链接https://godbolt.org/z/vxj7dPqaj 输出: 想知道这是一个错误吗?
我是C++的新手,我写了一个小程序来了解赋值如何处理对象。这个页面(http://www.cplusplus.com/doc/tutorial/classes2/)的cpp文档提示我这样做。在这一页上,它指出: 隐式版本[复制赋值操作符]执行浅层复制,这适用于许多类,但不适用于具有指向对象的指针的类,这些对象处理其存储。在这种情况下,不仅类会冒两次删除指向对象的风险,而且赋值会通过在赋值之前不删除
在 Go 语言开篇中我们已经知道,Go 语言与 C 语言之间有着千丝万缕的关系,甚至被称之为 21 世纪的C语言。 所以在 Go 与 C 语言互操作方面,Go 更是提供了强大的支持。尤其是在 Go 中使用 C,你甚至可以直接在 Go 源文件中编写 C 代码,这是其他语言所无法望其项背的。 格式: 在 import "C" 之前通过单行注释或者通过多行注释编写C语言代码 在 import "C" 之
上这个简单的课... JLS的第8.8.9节指出,“如果一个类不包含构造函数声明,那么默认构造函数将被隐式声明。”它还说,只要我们不在类中,那么“默认构造函数只是调用没有参数的超类构造函数。” 因此,因为类扩展了,我们被迫通过调用的构造函数,作为隐式创建的默认构造函数的一部分。 同样地... 即使我们显式地为Gen声明构造函数,JLS的第8.8.7节规定“如果构造函数体不是以显式构造函数调用开始,
更新1:根据建议添加了打印“this”。 更新2:拆分成几个文件,尝试阻止gcc优化。 更新3:记录复制构造函数并输入添加函数。 更新4:在main中添加了Clang和第二个cout的输出。 我希望参数析构函数作为函数中的最后一条语句被调用。从今以后,我希望下面的代码能够提供以下输出。 使用MSVC(Visual Studio)时,输出与预期的一样。但GCC(4.8.2-19ubuntu1)输出以