从方法c ++返回对象

时间:2014-03-10 10:21:41

标签: c++ reference local-variables

我在程序中创建了这个类

Node.h

class Node {
private:
    std::string id;
    double latitude;
    double longitude;
public:
    Node();
    Node(const Node& orig);
    Node(std::string id, double lat, double lon);
    virtual ~Node();

    void SetLongitude(double longitude);
    double const & GetLongitude() const;

    void SetLatitude(double latitude);
    double const & GetLatitude() const;

    void SetId(std::string id);
    std::string const & GetId() const;
};

Node.cpp

    Node::Node() {
}

Node::Node(const Node& orig) {

    this->id = orig.id;
    this->latitude = orig.latitude;
    this->longitude = orig.longitude;
}

Node::~Node() {
}

Node::Node(std::string id, double lat, double lon){
    this->id = id;
    this->latitude = lat;
    this->longitude = lon;
}

void Node::SetLongitude(double longitude) {
    this->longitude = longitude;
}

double const & Node::GetLongitude() const {
    return longitude;
}

void Node::SetLatitude(double latitude) {
    this->latitude = latitude;
}

double const & Node::GetLatitude() const {
    return latitude;
}

void Node::SetId(std::string id) {
    this->id = id;
}

std::string const & Node::GetId() const {
    return id;
}

我创建了一个返回节点的方法

Node& GeomertyHelper::GetPerpendicularPoint(double pointLat, double pointLon, Node front, Node back) const
{
    Node node;
    node.SetLatitude(x4);
    node.SetLongitude(y4);

    return node;
}

然后我从这个方法中得到了值。

Node projectionPoint = GeomertyHelper::Instance().GetPerpendicularPoint(lat, lon,
                Node("",nearestNode.GetLatitude(), nearestNode.GetLongitude()),
                Node("",frontNodeLat, frontNodeLon));

double frontNodeLat1 = projectionPoint.GetLatitude();
double frontNodeLon1 = projectionPoint.GetLongitude();

std::cout << std::fixed;
std::cout << std::setprecision(7) << "DIS= Lat------->>>>>" << frontNodeLat1;
std::cout << std::setprecision(7) << "DIS= Lon------->>>>>" << frontNodeLon1 << std::endl;

但我的价值是0。

4 个答案:

答案 0 :(得分:2)

您正在返回对本地对象的引用。那太糟糕了! 当函数退出时,对象将被销毁,最终得到一块不属于你的内存。

Node& GeomertyHelper::GetPerpendicularPoint

答案 1 :(得分:2)

您将在GeomertyHelper::GetPerpendicularPoint中返回对临时对象的引用。您应该让方法返回Node而不是Node&,因为当前方法会导致未定义的行为。

编辑:分配和返回Node*也可以。但是这不应该是必要的,因为Node对象在返回它时可能不会被复制,原因是返回值优化。

答案 2 :(得分:1)

这样做时:

Node node;
node.SetLatitude(x4);
node.SetLongitude(y4);

return node;

在堆栈上分配节点,退出函数后,堆栈被释放,因此节点在内存中变为无效位置,这会导致未定义的行为。

你应该返回Node*之类的内容并使用new进行分配,这样它就会在堆中放置,并且不会在函数退出时被释放:

Node* GeomertyHelper::GetPerpendicularPoint(double pointLat, double pointLon, Node front, Node back) const
{
    Node* node = new Node();
    node.SetLatitude(x4);
    node.SetLongitude(y4);

    return node;
}

但是在这里你不应该忘记在完成它之后做delete node,否则会导致内存泄漏。

答案 3 :(得分:1)

可以返回对所有权为 secure 的对象的引用。我的意思是,如果在使用返回的对象引用期间保证对象处于活动状态,则可以返回引用。如果您使用的“经理”类型对象在整个流程生命周期中都处于活动状态,则会出现这种情况。

问题是您的对象是临时的,并且在您尝试使用它时它将被删除。你们很多人都没有注意到这一点,因为被引用的内存可能无法立即清理掉。但是,它会在某些时候发生,这将导致崩溃或其他一些奇怪的行为。

至于替代方案,你不应该返回一个原始指针IMO,因为在这种情况下谁“拥有”该对象?创造它的人还是使用它的人?您应该返回std::unique_ptr<Node>。这使得使用Node的代码是所有者的模糊性降低。它还强制调用代码决定它想要用它做什么。它必须存储在更高的范围或被销毁。

std::unique_ptr<Node> GeomertyHelper::GetPerpendicularPoint(double pointLat, double pointLon, Node front, Node back) const
{
    std::unique_ptr<Node> node( new Node() );
    node->SetLatitude(x4);
    node->SetLongitude(y4);
    return node;
}

注意:这里不需要返回指针 ...我上面的警告真的不适用于你可以返回值的地方(这就是你应该做的)在这里)。