지 않고 왜 부르스의 생성자의 인스턴스에서 해당 클래스에서는 C++?

StackOverflow https://stackoverflow.com/questions/2146901

  •  23-09-2019
  •  | 
  •  

문제

할 수 있는 객체의 클래스는 호출의 소멸자는 클래스 경로,그것은 정기적인 기능입니까?왜 그것의 생성자를 호출 같은 클래스의 하나로 정기적인 기능을 가지고 있는가?왜 컴파일러를 중지에서 우리에게는 이것을 하고 있는가?

예를 들어:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles
 objC.c() ;  // compilation error
}
도움이 되었습니까?

해결책

By definition, a constructor is only called once, when the object is created. If you have access to an object, then it must have been created, so you're not allowed to call the constructor again - this is the reason why explicit constructor calls are not allowed. Similarly, destructors must only be called once, when the object is destroyed. If this could always done automatically, then the language would also forbid explicit destructor calls.

However, in some circumstances, you might want precise control over memory management, and the ability to explicitly create and destroy objects within memory that you are managing. For this purpose, the language provides "placement new" to create an object at an arbitrary location, and explicit destructor calls to destroy objects created this way. An explicit constructor call wouldn't be useful, since you need to be able to specify the location of the new object - so you get "placement new" instead. An explicit destructor call is sufficient, so there's no need to invent some sort of matching "placement delete".

So: there is no valid use for explicit constructor calls, so they are not allowed. There is a valid use for explicit destructor calls, so they are (syntactically) allowed, with the rule that you must only ever use them on objects that won't otherwise be destroyed, i.e. objects created using "placement new", and in that case call them exactly once. Using them in any other way, like so many C++ errors, will compile but give undefined behaviour.

다른 팁

나는 당신을 생각할 수 있는 명시적으로 호출하여 소멸자를 확인하는 경우에는 인스턴스로 대체/으로 다시 호출하여 배치 새:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

int main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles
 new (&objC) c;  // placement new invokes constructor for the given memory region
}

나는 본 적이 연습,그러나 그것은 논리적으로 작동해야(하지 않는 c 의 생성자를 던질 수 있는 경우에,내가 상상하는,지금은 느슨한 휴식하는 동안 스택 해제).

그러나,당신은 아마 그냥 지정:

objC = c();

는 경우에는 소멸자가 부작용에 관심이 있다,구현 할당 복사본을 사용하여-and-swap 관용구는 소멸자에 대해 호출되는"왼쪽"값입니다.

A destructor must be called on an existing instance of a class - destructing the instance is what it does. A constructor creates a brand new instance of a class, so calling on an existing instance makes no sense.

This is similar to the way new and delete work:

int * p = new int;    // call to new needs no existing instance
delete p;             // call to delete requires existing instance

And note in your code, the object would be destroyed twice, once explicitly, and once implicitly at the end of its enclosing scope. You typically only explicitly call a destructor if you are doing something unusual, probably involving the use of placement new.

If you really need to do something like this, just create an additional function and call it from outside AND from the constructor itself, but let's see what happens when you do need such a call:

#include<new>

class A
{
//members
};

int main()
{
//allocate buffer
char* buffer = new char[sizeof(A)];
//construct A on that memory space
A * ptrToA = ::new (buffer) A();
//destroy the object
ptrToA->~A();
//deallocate the buffer
delete[] buffer;
}

One instance where you can find placement new usage is the standard containers. The allocator takes in the responsibility to allocate the buffer (allocate member) and the objects are constructed over that buffer as they are added into the container. For example, when you do reserve on vector object, it reserves the space for N objects meaning allocates space for N objects but does not construct them. Then when you do push_back etc, to add elements, they are created over that buffer. Basically, it is a technique to reduce the overhead of repeated calls to memory allocation function. And then when done, the vector destructor would destroy the objects calling the destructor explicitly for all objects in it and then call the deallocate() function of the allocator to release the memory. Hope this helps.

Try this out :

obj.ClassName::ClassName() ; // it works in VC 6.0 compiler

Another way to think about the restriction is that a constructor is not just another function. Consider its definition: unlike other functions, it has no return value, and it may have an initializer list. That it just happens to have most of the syntax of a function is kind of a coincidence; it really exists only for the purpose of initializing a new instance of an object.

The constructor is there "c()" used with new, i.e.

c objC = new c();

If you want to call your constructor outside of the actual construction of the class instance then you either haven't understood the purpose of the constructor or are trying to put functionality in there that shouldn't be there.

You are asking about a particular style of syntax more than a language limitation. C++ allows you to call an object's constructor or destructor.

c objC;
objC.~c();  // force objC's destructor to run
new(&objC); // force objC's constructor to run

Why did the language designers not use this syntax instead?

c objC;
delete(&objC) c; // force objC's destructor to run
new(&objC) c;    // force objC's constructor to run

Or why not:

c objC
objC.~c(); // force objC's destructor to run
objC.c();  // force objC's constructor to run

My opinion as to why they chose the syntax they did: The first alternative is more flexible than the second. I can call the constructor / destructor on any address not just an instance. That flexibility is needed for allocation, but not for destruction. Also the first option's delete seems to be very dangerous once virtual destructors get in to the mess.

you can invoke the constructor of an instance's class using typeof:

class c
{
public:
   void add() ;
   c();
   ~c() ;
};

void main()
{
 c objC  ;
 objC.add() ;
 objC.~c() ; // this line compiles (but is a bad idea)
 typeof objC otherObjC;  // so does this.
}

This does not affect the value of the instance objC, but creates a new instance otherObjC using objC's class constructor.

Note: this may do something you don't expect if the static type is a baseclass of the dynamic type of the instance you have.

Who says you can't? You just have to know how.

void Foo::Bar() {
  *this = Foo(); // Reset *this
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top