#c 11
#c 11
Вопрос:
Я создал класс «config», который содержит 12 значений bool, организованных в std::array. Класс имеет функцию «обледенения», которая возвращает двойное значение. Пытаясь упорядочить вектор из 2 ^ 12 (4096) конфигураций через std:: sort (содержащийся в #include ), используя написанный мной предикат, я получаю ошибку ошибки сегментации.
Уменьшение вектора до 205 (не на 1 больше) устраняет ошибку, но я не знаю почему. Если я сделаю вектор длиной 4096 и попытаюсь отсортировать только небольшую часть, он будет работать до тех пор, пока длина части не достигнет 175 . Сокращение вектора, например, до 1000, ограничивает частичную сортировку примерно до 20, прежде чем она выдаст ошибку сегментации.
#include <array>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
class config {
public:
config (){ //constructor, default
array<bool,12> t;
for (boolamp; b: t){
b=false;
}
val=t;
g=1;
}
config (const configamp; fro): val(fro.val){}; //copy constructor
array<bool,12> get_val(){ return val; } //returns the array
void set_tf(int n, bool tf){ val[n]=tf; } //sets a certain boolean in the array to false/true
void set_g(double d){ g=d; } //this sets the constant for calculation to a number
void print(){
cout<<"values: ";
for (auto b: val){ cout<<b<<" "; }
cout<<endl;
}
config amp; incr(int n=1){ //this increases the vector by 1 following the rules for binary numbers, but has the digits reversed
for(int j=0; j<n; j ){
int i=0;
bool out=false;
while(val[i]==true){
val[i]=false;
i ;
}
val[i]=true;
}
return *this;
}
double energy(){
int ct=0;
int cf=0;
for(auto b:val){ if(b==true){ ct ; } else { cf ; } }
return (abs(ct-cf));
}
double icing(){ //here is the "value" for ordering purposes
int n=0;
for(int i=0; i<11; i ){
if(val[i]!=val[i 1]){ n ; }
}
double temp=-g*n this->energy();
return temp;
}
private:
array<bool,12> val;
double g;
};
bool pred (config c1, config c2){ return c1.icing()>c2.icing(); } //this sets the ordering predicate
template <typename T> //this orders the vector
void csort (vector <T>amp; in){
sort(in.begin(), in.end(), pred);
}
int main(){
vector<config> v;
for (int i=0; i<4096; i ){ //cicle that creates a vector of successive binaries
for(autoamp; c:v){
c.incr();
}
config t;
v.push_back(t);
}
sort(v.begin(), v.begin() 174, pred); //this gives seg.fault when 175
csort(v); //this gives segmentation fault when the vec is 206 long or longer
}
Я ожидал, что код упорядочит вектор, но он переходит в ошибку сегментации.
Ответ №1:
Ваша программа имеет неопределенное поведение в sort
функции, потому что ваш предикат принимает config
по значению, поэтому создаются копии, и в этом месте вызывается конструктор копирования, который копирует только массив val
, но не g
.
bool pred (config c1, config c2){ return c1.icing()>c2.icing(); }
// takes by value, copy ctor is called
config (const configamp; fro): val(fro.val){}; // only val is copied, g HAS GARBAGE VALUE
// icing in pred uses g !! - stric weak ordering is violated because g has GARBAGE VALUE
Исправление 1:
передача конфигурации с помощью const configamp;
:
bool pred (const configamp; c1, const configamp; c2){ return c1.icing()>c2.icing(); }
или исправить 2:
g
инициализируется в конструкторе копирования:
config (const configamp; fro): val(fro.val), g(fro.g){};
Комментарии:
1. Большое спасибо! Я пошел со вторым подходом, потому что первый дает проблемы, потому что функция обледенения не определена как const , поэтому она начинает выдавать «игнорирует ошибку квалификаторов [f-permissive]». Второй подход — хороший улов, спасибо! Дело в том, что сначала класс должен был быть упорядочен по энергии, затем были внесены некоторые изменения, которые привели к добавлению частного значения g и относительного термина. При этом я забыл добавить g в конструктор копирования и только добавил его в конструктор … :/ глупый я