This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

C6000 C++ non-POD default-initialization

I am currently implementing some small utility classes such as a smart pointer in C++. Now when I look at the assembly output, there seems to be some considerable overhead that I cannot quite explain. In particular, all non-POD classes seem to be memset to 0 before any other initialization. Currently, I have

struct Base
{
  virtual ~Base() {}
Base() : x(11), y(22) {} int x; int y; }; struct Derived : Base { double z; }; void function() { Derived *ptr = new Derived(); delete ptr; }

Now function() roughly translates to:

Derived *ptr = operator new(24);
memset(ptr, 0, 24);
ptr->vtbl = vtbl_for_Base;
ptr->x = 11;
ptr->y = 22;
ptr->vtbl = vtbl_for_Derived;
call ptr->vtbl->destructor
return

The compiler command line is:

"C:/ti/ccsv5/tools/compiler/c6000_7.4.7/bin/cl6x" -mv6400 --abi=eabi -O3 -ms3 --include_path="C:/project/inc" --rtti --cpp_default --display_error_number --diag_warning=225 --call_assumptions=3 -k --temp_directory="C:/project/obj/CCS5/Release" --obj_directory="C:/project/obj/CCS5/Release" --asm_directory="C:/project/obj/CCS5/Release" --list_directory="C:/project/obj/CCS5/Release" --preproc_with_compile --preproc_dependency="C:/project/obj/CCS5/Release/my_unique_ptr_test.pp"  "C:/project/src/my_unique_ptr_test.cpp"


My understanding is that (a) the implicitly defined default constructor Derived::Derived() should behave as if defined without a mem-initializer-list, so POD-members should remain uninitialized (of course, it is not an error to initialize them, but it's unexpected and has quite some performance impact).

The memset causes quite some overhead, mostly because the compiler doesn't use any memset intrinsic and instead generates a regular function call with the usual overhead.

As a side-note, I also wonder why the compiler sets the vtbl to vtbl_for_Base if it is inlining the Base constructor anyway and if the vtbl isn't accessed anywhere.

Am I doing something wrong? Are there any compiler flags I am missing?

Kind regards

Markus

  • To answer my own question: I was wrong. In value-initialization, if there is no user-declared constructor, members are value-initialized in turn. Sorry for that.

    However, I still wonder if it wouldn't be a lot more efficient to initialize small classes more directly, in particular

    struct Empty
    {
      void operator()();
    };
    
    void test() { Empty()(); }

    generates a call to memset (of 1 byte (== sizeof(Empty)) with all zeros).

  • The next major version of the C6000 compiler will do away with the memset for empty classes, but it will still emit a memset call for a 1-byte class.  I've submitted SDSCM00050884 to request this optimization.