wanglinski wanglinski - 5 months ago 9
Linux Question

What is the cause of the difference in return value between Linux and Windows and how to fix it?

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;
}

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.