Question

In trying to understand this answer, it seems that new can be classified as a "copy constructor" and delete sometimes as a "trivial destructor".

I can find next to nothing (that I can quickly grasp) on "trivial assignment" except that it is "trivial if it is implicitly declared, if its class has no virtual member functions or virtual base classes, and if its direct base classes and embedded objects have a trivial assignment operator".

I found a question on yahoo about implicit declaration, but to my surprise, it did not answer.

My brain hurts after reading about virtual member functions.

Besides, I'm a monkey-see-monkey-do programmer, so the only way I'm going to get this is to see it in action. Please explain with respect to the above definition of "trivial" by using the example provided in the first answer, that std::string has a trivial assignment operator by using new or delete or for a less apparent reason.

Était-ce utile?

La solution

New can use a copy constructor, and delete uses a destructor. The copy constructor or destructor may be trivial.

That being said, there is a STRONG chance that you will not need to worry about whether a constructor/destructor is trivial for a long time.

new calls a constructor to construct the object. If the one argument to the constructor of type T is an instance of T that is a copy constructor: you are trying to construct an instance of one object from another

class Foo
{
    public:
        Foo(int x) // not a copy constructor
        : mX(x)
        { }

        Foo(const Foo& inOther) // copy constructor
        : mX(inOther.mX)
        { }
    private:
        int mX;
};

class Bar
{
    public:
        Bar(int x)
        : mX(x)
        { }

        // no copy constructor specified.. C++ will build an implicit one for you
    private:
        int mX;
} 
};

Foo a(1);  // uses the first constructor (not a copy)
Foo b(a); // uses a copy constructor
Foo c = a; // copy constructor

Foo* d = new Foo(1); // construct a new instance of Foo (not a copy)
Foo* e = new Foo(a); // copy

Bar f(1); // normal constructor
Bar g(f); // IMPLICIT copy constructor

If your class does not have a copy constructor, like Bar, C++ usually provides you one (always provides you one unless you have an explicit constructor or delete the copy constructor with a C++11 keyword). This copy constructor is very straightforward: it copies each member of your class.

A trivial copy constructor is special. A trivial copy constructor can only be created when the copy constructor is implicitly created for you by the compiler and:

  • All members of your class are trivially copyable
  • You do not have any virtual methods or virtual base classes
  • All of your base classes are trivially copyable.

If you specify a constructor in your class, it is not trivial, by definition. Foo does not have a trivial copy constructor because it is user defined. Bar has an implicit copy constructor because it is not user defined. The implicit copy constructor IS trivial, because copying mX is trivial (copying ints is trivial).

Similar rules go for destructors. A trivial destructor follows the same rules, and delete

WHat does it do for you? The spec lists a few key behaviors about trivial constructors/destructors. In particular, there's a list of things you can do if you have a trivial constructor and destructor that are illegal otherwise. However, they are all very nuanced, and unimportant to 99.9% of C++ code development. They all deal with situations where you can get away with not constructing or destructing an object.

For example, if I have a union:

union MyUnion {
    int x;
    ClassA y;
    ClassB z;
}

If y and z have trivial constructors and destructors, C+ will write a copy constructor for that union for me. If one of them has a non-trivial constructor/destructor, I have to write the copy constructor for the union myself.

Another thing you can do is fast destruction of an array. Usually, when you delete an array, you have to make sure to call the destructor on every item. If you can prove that the destructor of each element is trivial, then you are allowed to skip destroying the elements, and just free the memory. std::vector does this under the hood (so you don't have to)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top