2016-03-26 4 views
0

Warum wird mein const ref in diesem Code ungültig und wie kann dies vermieden werden? Ich kann nicht kopieren, das ist der Flaschenhals in meiner Anwendung.Warum wird mein const ref ungültig?

class Foo { 
public: 
    const std::string& string() const { 
     return string; 
    } 

private: 
    std::string string = "asdf"; 
}; 

Foo foo; 
std::vector<std::pair<const std::string&, int>> invalid; 
for (int i = 0; i < 5; i++) { 
    invalid.emplace_back(std::make_pair(foo.string(), i); 
    // after this line invalid[i].first is invalid 
} 
+4

Template-Parameter Abzug funktioniert so, dass '' make_pair' zurück std :: pair 'in Ihren Anruf; Dann konstruiert 'emplace' 'std :: pair ' von diesem. Also ist die Referenz an das Mitglied eines temporären Paares gebunden, nicht an 'foo.string'. Mache es 'invalid.emplace_back (std :: pair (foo.string(), i));' –

+0

Woher weißt du, dass 'invalid [i] .first' ungültig ist? 'Foo' ist nicht mit einem Move-Konstruktor zuweisbar. Ist das für ein Vektorelement zulässig? (Echte Frage - Ich habe C++ 11 noch nicht vollständig eingeholt.) Funktioniert es, wenn Sie als Elementtyp 'std :: pair ' verwenden? –

+0

@IgorTandetnik - Machen Sie das eine Antwort, so kann ich es bitte! –

Antwort

1

Igor Tandetnik schon darauf, das Problem in Ihrem Code aus. FWIW, ich denke nicht, dass es eine gute Idee ist, Container zu haben, die auf andere Objekte Bezug nehmen, auf jeden Fall - es gibt eine implizite Abhängigkeit von der relativen Liftzeit von Objekten. Sie betrachten können eine shared_ptr to const string verwenden, wie in der folgenden:

#include <string> 
#include <memory> 
#include <vector>                               
class Foo { 
public: 
    const std::shared_ptr<const std::string> string() const { 
     return _string; 
    } 

private: 
    std::shared_ptr<std::string> _string = std::make_shared<std::string>("asdf"); 
}; 

int main() 
{ 
    Foo foo; 
    std::vector<std::pair<std::shared_ptr<const std::string>, int>> invalid; 
    for (int i = 0; i < 5; i++) { 
     invalid.emplace_back(std::make_pair(foo.string(), i)); 
    } 
} 
1

make_pair eine pair<std::string,int> zurückkehrt, kein pair<const std::string&, int>, weil der Standard erforderlich macht, so zu sein.

template <class T1, class T2> 
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y); 

§ 20.3.3 - 8

Returns: pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));

wo V1 und V2 werden wie folgt bestimmt: Ui decay_t<Ti> für jeden Ti sein lassen. Dann ist jedes Vi X & , wenn Ui gleich reference_wrapper ist, sonst ist Vi Ui.

Dies soll nach dem Standard arbeiten:

invalid.emplace_back(std::make_pair(std::ref(foo.string()), i)); 

und dies nach mir:

invalid.emplace_back(decltype(invalid)::value_type(foo.string(), i)); 
+0

Sehr gute Referenzierung! –