2015-05-29 2 views
1

Я довольно новыми для программирования на C++ и мне было интересно, что-то:C++ оператор перегрузки обратный указатель

всякий раз, когда я вижу, оператор перегрузки в C++ это делается так:

#ifndef STONE_H 
#define STONE_H 

class Stone { 
    private: 
    int weight; 

    public: 
    ....... 

    Stone operator+(const Stone& s) { 
     Stone stone; 
     stone.weight = this->weight + s.weight; 
     return stone; 
    } 

    ....... 
} 


#endif 

Но когда " + ", он создает объект« камень »и возвращает копию этого. Это не может быть хорошо для производительности при работе с огромными объектами?

не лучше ли использовать динамическую память для этого, как в примере ниже:

Stone * operator+(const Stone& s) { 
    Stone * stone = new Stone; 
    stone->weight = this->weight + s.weight; 
    return stone; 
} 

Или я вижу это неправильно?

Заранее спасибо

+2

видят это: http://stackoverflow.com/questions/ 12953127/what-are-copy-elision-and-return-value-optimization – NathanOliver

+3

Кто выпустит объекты? А вот 'a + b + c'? – StoryTeller

+1

Всегда создавайте пары с удалением (с бинарным оператором, который, скорее всего, запускается в утечку памяти). Первый подход просто хорош (взгляните на оптимизацию возвращаемых значений) –

ответ

2

Пытаясь рассуждать вещи не особо точный способ оценки производительности: Вы должны фактически написать программу для меры ли не одна реализация лучше, чем другой.

Существует несколько способов, при которых копия не будет вообще; оптимизация названного значения возвращаемого значения (NRVO) и назначение перемещения здесь являются важными идеями.

Даже если вы решите, что хотите сделать что-то вроде своего предложения, вы не должны реализовывать его так же, как и у вас, поскольку он имеет неправильную семантику: у вас было operator+, чтобы вернуть указатель к чему-то, а не вещь. Кроме того, работа с указателями (особенно голыми указателями) является рискованной, поскольку она дает вам гораздо больше возможностей совершать ошибки.

Если вы хотите реализовать что-то вдоль этих строк, вам нужно обернуть семантику указателя в классе, который предоставляет семантику значений.

0

Оказывается, на текущем уровне, это немного по-другому:

#include <iostream> 

class big { 
    int* v; // Demonstration purposes. A smart pointer or a standard container would be better. 
    public: 
    big& operator+=(big& o) { 
    for (int i=0;i<1000;++i) { 
     v[i] += o.v[i]; 
    } 
    return *this; 
    } 

    big(int val = 0) 
     : v{new int[1000]} // We're using RAII to prevent resource leaking. 
    { 
    std::cout << "a construction.\n"; 
    for (int i=0;i<1000;++i) { 
     v[i] = val; 
    } 
    } 

    // Copy constructor 
    big(big& o) 
     : v{new int[1000]} 
    { 
    std::cout << "a copy construction.\n"; 
    for (int i=0;i<1000;++i) { 
     v[i] = o.v[i]; 
    } 
    } 

    // Move assignment 
    big& operator=(big&& o) { 
    std::cout << "a move assignment.\n"; 
    if (v) delete[] v; 
    v = o.v; 
    o.v = nullptr; 
    } 

    // Move constructor 
    big (big&& o) { 
    std::cout << "a move construction.\n"; 
    v = o.v; 
    o.v = nullptr; 
    } 

    ~big() { 
    if (v) delete[] v; 
    } 
}; 

// a will be move-constructed if using a temporary, or copy-contructed if not. 
// The result will always be passed by a cheap move 
big operator+(big a, big& b) { 
    return std::move(a += b); 
} 

int main() { 
    big a{1}; 
    big b{2}; 
    big c{3}; 

    big d = a+b+c; 
} 

Выход: (с комментариями) добавленными

a construction. // Constructed a 
a construction. // Constructed b 
a construction. // Constructed c 
a copy construction. // a+b <- a copied into parameter "a" of operator+. b is passed by reference. 
a move construction. // The temporary from the operation above, moved into parameter "a" of operator+. c is passed by reference. 
a move construction. // d is move constructed from the temporary generated by a+b+c. 
Смежные вопросы