This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libstdc++/32618] New: std::vector calls uneccessary constructors instead of inplace construction of first object
- From: "oliver at kfs dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 4 Jul 2007 00:46:12 -0000
- Subject: [Bug libstdc++/32618] New: std::vector calls uneccessary constructors instead of inplace construction of first object
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
When using resize() and push_back(), an baseline instace of T is created and
then the new members are assigned via the copy constructor.
If T is complex this begins to add a non-negligible overhead, especially for
push_back.
Is there a reason /not/ to replace the [first] create & copy with in-place
construction?
Sample code:
#include <iostream>
struct Foo {
Foo() { cout << "ctor " << this << endl ; }
Foo(const Foo& rhs) { cout << "copyctor " << this << " from " << &rhs <<
endl ; }
~Foo() { cout << "dtor " << this << endl ; }
} ;
typedef vector<Foo> FOO ;
int main(int argc, char* argv[]) {
FOO bar;
cout << "pushing" << endl ;
bar.push_back(Foo()) ;
cout << "end of program" << endl ;
}
Compilation:
[osmith@fedex src]$ g++ -v -save-temps -O2 -g2 -Wall -o test -lstdc++
test.cpp
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk
--disable-dssi --enable-plugin
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic
--host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20070105 (Red Hat 4.1.1-51)
/usr/libexec/gcc/i386-redhat-linux/4.1.1/cc1plus -E -quiet -v -D_GNU_SOURCE
test.cpp -mtune=generic -Wall -fworking-directory -O2 -fpch-preprocess -o
test.ii
ignoring nonexistent directory
"/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/i386-redhat-linux
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/backward
/usr/local/include
/usr/lib/gcc/i386-redhat-linux/4.1.1/include
/usr/include
End of search list.
/usr/libexec/gcc/i386-redhat-linux/4.1.1/cc1plus -fpreprocessed test.ii
-quiet -dumpbase test.cpp -mtune=generic -auxbase test -g2 -O2 -Wall -version
-o test.s
GNU C++ version 4.1.1 20070105 (Red Hat 4.1.1-51) (i386-redhat-linux)
compiled by GNU C version 4.1.1 20070105 (Red Hat 4.1.1-51).
GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=129076
Compiler executable checksum: 4720743fdfefd64206c8550433f6e508
as -V -Qy -o test.o test.s
GNU assembler version 2.17.50.0.6-2.fc6 (i386-redhat-linux) using BFD version
2.17.50.0.6-2.fc6 20061020
/usr/libexec/gcc/i386-redhat-linux/4.1.1/collect2 --eh-frame-hdr -m elf_i386
--hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 -o test
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../crt1.o
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../crti.o
/usr/lib/gcc/i386-redhat-linux/4.1.1/crtbegin.o
-L/usr/lib/gcc/i386-redhat-linux/4.1.1 -L/usr/lib/gcc/i386-redhat-linux/4.1.1
-L/usr/lib/gcc/i386-redhat-linux/4.1.1/../../.. -lstdc++ test.o -lstdc++ -lm
-lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/i386-redhat-linux/4.1.1/crtend.o
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../crtn.o
Output:
pushing
ctor 0xbfa3d327
copyctor 0x8c87008 from 0xbfa3d327
dtor 0xbfa3d327
end of program
dtor 0x8c87008
If resize were being called, it the copyctor would be used to copy /0xbfa3d327/
into each new uninitialized instance:
resizing
ctor 0xbfa3d327
copyctor 0x8c87008 from 0xbfa3d327
copyctor 0x8c8700c from 0xbfa3d327
copyctor 0x8c87010 from 0xbfa3d327
dtor 0xbfa3d327
end of program
dtor 0x8c87008
dtor 0x8c8700c
dtor 0x8c87010
The optimization I am suggesting would produce the following [approximate]
output:
pushing
ctor 0x8c87008
end of program
dtor 0x8c87008
If resize() was being called instead of push_back, it might look like this:
resizing
ctor 0x8c87008 /first entry in the pool/
copyctor 0x8c8700c from 0x8c87008 /copy ctor of second entry from first/
copyctor 0x8c87010 from 0x8c87008 /copy ctor of third entry from first/
...
end of program
dtor 0x8c87008
dtor 0x8c8700c
dtor 0x8c87010
--
Summary: std::vector calls uneccessary constructors instead of
inplace construction of first object
Product: gcc
Version: 4.1.1
Status: UNCONFIRMED
Severity: minor
Priority: P3
Component: libstdc++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: oliver at kfs dot org
GCC host triplet: i386-redhat-linux
GCC target triplet: i386-redhat-linux
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32618