[英]Problems with emplace_back and move assignment constructors
給出以下代碼
test.h:
#ifndef __graph_aufbau_header__
#define __graph_aufbau_header__
#include <vector>
#include <queue>
#include <string>
using namespace std;
class Knoten {
public:
unsigned int nummer;
double x_1;
double x_2;
unsigned int abstand;
Knoten(unsigned int num, double x1, double x2) : nummer(num), x_1(x1), x_2(x2), abstand(-1) {};
Knoten(Knoten&& anderer) : nummer(anderer.nummer), x_1(anderer.x_1), x_2(anderer.x_2), abstand(anderer.abstand) {};
Knoten& operator=(Knoten&& anderer) = default;
};
class Kante {
public:
unsigned int quellknotennum;
unsigned int zielknotennum;
unsigned int gewicht;
Kante(unsigned int qnum, unsigned int znum, unsigned int gew)
: quellknotennum(qnum), zielknotennum(znum), gewicht(gew)
{};
Kante(Kante&& andere)
: quellknotennum(andere.quellknotennum),
zielknotennum(andere.zielknotennum),
gewicht(andere.gewicht) {};
Kante& operator=(const Kante& andere) = default;
inline bool operator<(const Kante& kante_2){
return this->quellknotennum < kante_2.quellknotennum;
};
};
class Offset {
public:
unsigned int knoten_num;
unsigned int kanten_num;
Offset(unsigned int knnum, unsigned int kanum)
: knoten_num(knnum), kanten_num(kanum)
{};
Offset(Offset&& anderer)
: knoten_num(anderer.knoten_num), kanten_num(anderer.kanten_num) {};
Offset& operator=(Offset& anderer) = default;
};
class Graph {
public:
vector<Knoten> coordList;
vector<Kante> edgeList;
vector<Offset> edgeOffsets;
//vector<unsigned int> abstand;
Graph() : coordList(), edgeList(), edgeOffsets(){};
void knoten_einlesen(double x_1, double x_2);
void kante_einlesen(unsigned int quellknoten, unsigned int zielknoten, unsigned int gewicht);
void offset_einlesen(unsigned int nummer, unsigned int kante);
void einlesen(string quelle);
Knoten naechster_Nachbar(Knoten& knoten);
};
#endif
test.cc:
// kein iostream
#include <fstream> // benötigt für die Deklaration eines Dateistroms
#include <iostream>
#include <string>
#include <sstream> // zum Splitten
//#include <regex>
#include <cstdlib> // Zur Umwandlung von Strings in Doubles
#include <algorithm> // fuer find_if()
#include <queue>
#include <vector>
#include "test.h"
using namespace std;
void Graph::knoten_einlesen(double x_1, double x_2){
unsigned int neue_position = coordList.size();
coordList.emplace_back(neue_position, x_1, x_2);
}
void Graph::kante_einlesen(unsigned int knoten_1, unsigned int knoten_2, unsigned int gewicht){
edgeList.emplace_back(knoten_1, knoten_2, gewicht);
}
void Graph::offset_einlesen(unsigned int nummer, unsigned int kante){
edgeOffsets.emplace_back(nummer, kante);
}
void Graph::einlesen(string quelle){
ifstream datendatei(quelle);
if (datendatei.is_open()){
string aktuelle_zeile;
getline(datendatei, aktuelle_zeile);
unsigned int anzahl_knoten = stoi(aktuelle_zeile);
getline(datendatei, aktuelle_zeile);
unsigned int anzahl_kanten = stoi(aktuelle_zeile);
unsigned int nummer, position;
for(auto& knoten: coordList){
nummer = knoten.nummer;
auto erste_kante = find_if(edgeList.begin(), edgeList.end(), [nummer] (Kante kante)\
{return nummer == kante.quellknotennum;});
position = erste_kante - edgeList.begin(); // Position der ersten Kante, die mit dem Knoten verbunden ist, in edgeOffsets
offset_einlesen(nummer, position);
}
datendatei.close();
}
}
Knoten Graph::naechster_Nachbar(Knoten& knoten){
return coordList.at(edgeList.at(edgeOffsets.at(knoten.nummer).kanten_num).zielknotennum);
}
,我通過調用g++ -std=gnu++11 test.cc
收到以下錯誤:
test.cc: In member function 'Knoten Graph::naechster_Nachbar(Knoten&)':
test.cc:55:96: error: use of deleted function 'constexpr Knoten::Knoten(const Knoten&)'
return coordList.at(edgeList.at(edgeOffsets.at(knoten.nummer).kanten_num).zielknotennum);
^
In file included from test.cc:11:0:
test.h:10:11: note: 'constexpr Knoten::Knoten(const Knoten&)' is implicitly declared as deleted because 'Knoten' declares a move constructor or move assignment operator
class Knoten {
^~~~~~
In file included from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algobase.h:71:0,
from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/char_traits.h:39,
from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/ios:40,
from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/istream:38,
from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/fstream:38,
from test.cc:2:
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>]':
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:120:14: required from '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<Graph::einlesen(std::__cxx11::string)::<lambda(Kante)> >]'
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:161:23: required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<Graph::einlesen(std::__cxx11::string)::<lambda(Kante)> >]'
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:3817:28: required from '_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>]'
test.cc:44:57: required from here
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/predefined_ops.h:234:11: error: use of deleted function 'constexpr Kante::Kante(const Kante&)'
{ return bool(_M_pred(*__it)); }
^~~~~~~~~~~~~~~~~~~~
In file included from test.cc:11:0:
test.h:22:11: note: 'constexpr Kante::Kante(const Kante&)' is implicitly declared as deleted because 'Kante' declares a move constructor or move assignment operator
class Kante {
^~~~~
test.cc:43:99: note: initializing argument 1 of 'Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>'
auto erste_kante = find_if(edgeList.begin(), edgeList.end(), [nummer] (Kante kante)\
^
(不要錯過隱藏在右側的錯誤)
我已經嘗試了許多小時來解決此問題,而今天,我不知道這里出了什么問題。 顯然,代碼在方法naechster_nachbar(..)中調用了一個隱式刪除的類“ Knoten”的move構造函數-但我不知道為什么會這樣以及如何防止出現相應的錯誤消息。
另一部分(較大的部分,稍微模糊)可能是在函數einlesen(...)(lambda函數?)中的某處引起的,可能是與第一個部分相同的原因引起的。
給定的代碼不必能夠獨立編譯,甚至不必完整且有意義。 它的唯一目的是演示所生成的錯誤消息。 我無法進一步減小此最小示例的大小。 我們被迫使用C ++ 11(因此必須使用命令行選項)。
提前謝謝了!
Knoten Graph::naechster_Nachbar(Knoten&)
按值返回,因此嘗試復制Knoten
。 但這不能,因為該類僅具有move構造函數而沒有copy構造函數。
有趣的是,move構造函數實際上是從anderer
復制所有數據的,因此它可能只是一個復制構造函數。
您已為Knoten和Kante指定了移動構造函數,這使默認副本構造函數被刪除。 基本原理是,如果您編寫自己的move構造函數,則假定此類需要一些非平凡的邏輯,因此,如果為move構造函數/賦值運算符提供了此邏輯,則常規版本也將需要此邏輯。
如果添加以下內容,則代碼將編譯:
Knoten(const Knoten& anderer) = default;
Knoten& operator=(const Knoten& anderer) = default;
和
Kante(const Kante& anderer) = default;
但我不確定默認邏輯是否足以滿足您的課程要求。 您還應該考慮是否真的需要自己的移動構造函數/運算符。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.