Here is the code that I tried to return an object of a class. but I got different results from CentOs (gcc) and visual studio 2013. In the cls.cpp, with gcc, it works well, I get the results such as detector.name = “t_name”, detector.stride = 5. but the values in the detector are “” and 0 under vs2013. It seems in vs2013 the cls object is deconstructed. Why I got the different returns? and how to make it works well under visual studio? Thanks a lot.
cls.h
#pragma once #include <iostream> #include <string> #define OUT(x) do{ std::cout << x << std::endl;}while(0) template <class T> class IBuilder{ public: virtual ~IBuilder(){}; virtual T build() = 0; }; class cls { public: ~cls(); cls(const cls& origin); class Builder : public IBuilder<cls>{ private: std::string _name; int _stride = 4; double _cascThr = -1; public: Builder(const std::string name); ~Builder(); Builder* stride(int s); Builder* cascThr(double t); cls build(); friend cls; }; private: std::string _name; int _stride; double _cascThr; Builder* _builder; cls(Builder* builder); cls& operator=(const cls&);//prevent the compiler to generate copying assignment };
cls.cpp
#include "cls.h" using namespace std; cls::cls(const cls& origin){} cls::cls(cls::Builder* builder) { this->_builder = builder; OUT("cls(Builder*)"); this->_name = builder->_name; this->_stride = builder->_stride; this->_cascThr = builder->_cascThr; } cls:: ~cls(){ OUT("~cls()"); } cls::Builder::Builder(const string name){ OUT("Builder(string)"); this->_name = name; } cls::Builder::~Builder(){ OUT("~Builder() "); } cls::Builder* cls::Builder::stride(int s){ this->_stride = s; return this; } cls::Builder* cls::Builder::cascThr(double t){ this->_cascThr = t; return this; } cls cls::Builder::build(){ OUT("Build ACF Detector From Builder"); return cls(this); }
main.cpp
#include "cls.h" using namespace std; cls func(){ cls::Builder* builder = NULL; builder = new cls::Builder("t_name"); builder->stride(5); builder->cascThr(1.0); cls detector = builder->build(); return detector; } int _tmain(int argc, _TCHAR* argv[]) { cls tt = func(); // here I got different answers. return 0; }
Advertisement
Answer
You have got a copy constructor that does nothing.
cls::cls(const cls& origin){}
GCC probably does copy elision in the lines cls tt = func();
and cls detector = builder->build();
and it magically works. Maybe VS will do it too once you enable optimizations. Personally, I’d say it’s a bug in your code. If you have a copy constructor, then copy the origin object.