我们可以通过类指针显式调用析构函数,为什么不构造函数?有什么想法吗?
#include <iostream>
class Con {
public:
Con( int x ) : x( x ) {
}
private:
int x;
};
int main() {
Con* c = new Con( 1 );
//c->Con( 2 ); //illegal
c->~Con(); // ok!
delete c;
}
谢谢,
答案 0 :(得分:18)
你实际上可以调用它,只是语法不是调用成员方法的语法(析构函数是特殊情况),所以不能使用成员访问运营商。相反,您必须使用 placement-new 语法:
Con c;
c.~Con(); // destroy, now c is not a Con anymore
new (&c) Con(); // recreate, now c is a Con again
作为特殊情况,在C ++ 0x提议中,实际上在其中一个代码示例中使用,提供了在包含非的联合的情况下将union
重用为不同类型的方法POD元素:
union U {
int i;
float f;
std::string s;
};
int main() {
U u;
new (&u.s) std::string( "foo" );
u.s.~string();
u.i = 5;
}
}
答案 1 :(得分:12)
没有。你不能。
Con* c = new Con( 1 );
//c->Con( 2 ); //illegal
您已经在new
表达式中调用了构造函数。
当你有一个Con*
类型的有效指针时,你已经创建了一个对象。在“构造”对象上调用构造函数甚至没有意义。那么C ++为什么会允许呢?
答案 2 :(得分:2)
如果您不将构造函数和析构函数视为您调用的函数,那么对您来说会更容易。你不打电话给他们。您只能构造或销毁对象。而且,作为构造的一部分,构造函数体被执行。同样,作为对象破坏的一部分,执行析构函数体。
所以你可以在堆栈上构造对象
YourClass variable(constructor_arguments);
当它超出范围时会被自动销毁。
您还可以在堆上创建对象
YourClass * ptr = new YourClass(parameters);
要破坏此类对象,请使用运算符delete
delete ptr;
您还可以在自己提供的某些内存中构建一个对象(很少需要)
char * pool = new char[sizeof(YourClass)]
YourClass *ptr = new(pool) YourClass(parameters);
你明确地破坏了这样一个对象,语法看起来像函数invokation,但它更像是一个对象破坏
ptr->~YourClass();
在此行之后,您的对象不再存在。在其上调用任何内容是一种未定义的行为。而且您仍然需要管理为此对象分配的内存
delete[] pool;
所以,你的问题意味着'为什么我能明确地破坏一个我有指针但我无法构造它的对象'?你不能,因为它已经构建好了。
您还可以阅读C++ FAQ Lite explanation
答案 3 :(得分:0)
不,你不能按照你解释的方式调用类的构造函数,那是因为,c没有指向con类型的有效对象。
答案 4 :(得分:0)
您只能在对象构造时调用构造函数,因此它的名称。一旦构造了对象,我就没有理由为什么你想在同一个对象上再次调用它。如果你想做某事,你需要调用该类中定义的函数。
答案 5 :(得分:0)
构造函数的意图是在创建对象时调用。没有其他的。如果你有一个引用计数器来跟踪对象的数量,允许将构造函数作为函数调用会使计数器崩溃。
如果要重新初始化或重置对象,可以添加一个名为Reset()或Initialize()的函数,并从构造函数中调用它。然后,您还可以从对象指针调用Reset()或Initialize()。
答案 6 :(得分:0)
还有一种方法:
template <typename T, typename... Args>
using fn_ExternFunctionConstructorType = void(__thiscall T::*)(Args...);
template <typename RetType, typename T, typename... Args>
using fn_ExternFunctionType = RetType(__thiscall T::*)(Args...);
class __declspec(dllexport) CTest
{
public:
CTest()
{
std::cout << 6 << std::endl;
}
int bla(int val) { std::cout << val << std::endl; return -1; }
};
int main(int argc, char** argv)
{
FARPROC pFuncConstructor = GetProcAddress(GetModuleHandle(NULL), "??0CTest@@QAE@XZ");
FARPROC pFuncBla = GetProcAddress(GetModuleHandle(NULL), "?bla@CTest@@QAEHH@Z");
CTest* pTest = (CTest*)malloc(sizeof(CTest));
(pTest->*reinterpret_cast<fn_ExternFunctionConstructorType<CTest>&>(pFuncConstructor))();
(pTest->*reinterpret_cast<fn_ExternFunctionType<int, CTest, int>&>(pFuncBla))(99);
return 0;
}
编辑:接第二个构造函数调用
答案 7 :(得分:0)
Ofc你可以从对象实例中调用它,请参阅以下代码:
#include <iostream>
class foo{
public :
int foo_var;
foo(){
std::cout<<"foo_var = "<<foo_var<<std::endl;
}
};
int main()
{
foo * f = new foo();
// set foo_var
f->foo_var = 10;
// call constructor by passing object instanse
foo * f1 = new(f) foo;
std::cout<<(f==f1)<<std::endl;
system("pause");
return 0;
}
第二个输出是“foo_var = 10”,所以它正在工作。第三个输出是“true”然后(f == f1),这意味着构造函数不分配新的内存(运算符new,但我们传递一个指针,所以他不会分配另一个) 你真的很有用:
#include <iostream>
template <class t>
class smart_pointer{
t * p; // the real normal pointer
public :
smart_pointer()
{
p = (t*) malloc(sizeof(t)); // allocate memory
try{
new (p) t; // call the constructor
} catch (...) // if it throws any exception
{
free(p); // free p , dont use delete , because it will
// call the destroctor calling the destructor will cause
// freeing a not allocated memory that causes a crash
throw; // throw the exception what ever it was
}
}
~smart_pointer(){delete p;}
t operator = (t val) // assigment operator
{
*p = val;
return val;
}
operator t(){ // type casting operator , usually for std::cout
return *p;
}
};
int main()
{
smart_pointer<int> x;
x = 10;
std::cout<<x<<std::endl;
system("pause");
return 0;
}
建议阅读“有效的c ++”,“更有效的c ++”,“有效的现代c ++”书籍