2012-03-19 2 views
2

У меня есть класс Bar со ссылками на внутренней стороне одного из его членов (Bar::foo):член класса в качестве ссылки на другую: аварии в операторе присваивания

#include<vector> 
#include<algorithm> 

struct Foo{ 
    int x, y; 
}; 

struct Bar{ 
    Foo foo; 
    int &x, &y; 
    Bar(): x(foo.x), y(foo.y){} 
    // copy constructor and assignment operator 
    Bar(const Bar& other): foo(other.foo), x(foo.x), y(foo.y){} 
    Bar& operator=(const Bar& other){ foo=other.foo; return *this; } 
}; 

int main(void){ 
    std::vector<Bar> a, b; 
    Bar p; p.x=0; p.y=0; 
    a.push_back(p); 
    std::copy(a.begin(),a.end(),b.begin()); 
} 

Compiling с g++ (без каких-либо специальных опций), я получить сбой в операторе присваивания. Зачем?

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000400b29 in Bar::operator= (this=0x0, other=...) at ref2.cpp:14 
14  Bar& operator=(const Bar& other){ foo=other.foo; return *this; } 
(gdb) bt 
#0 0x0000000000400b29 in Bar::operator= (this=0x0, other=...) at ref2.cpp:14 
#1 0x00000000004016a0 in std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m<Bar*, Bar*> (
__first=0x405010, __last=0x405030, __result=0x0) at /usr/include/c++/4.6/bits/stl_algobase.h:329 
#2 0x000000000040148d in std::__copy_move_a<false, Bar*, Bar*> (__first=0x405010, __last=0x405030, __result=0x0) 
at /usr/include/c++/4.6/bits/stl_algobase.h:384 
#3 0x0000000000401157 in std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > >, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > > > (__first=..., __last=..., 
__result=...) at /usr/include/c++/4.6/bits/stl_algobase.h:422 
#4 0x0000000000400cc0 in std::copy<__gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > >, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > > > (__first=..., __last=..., __result=...) 
at /usr/include/c++/4.6/bits/stl_algobase.h:454 
#5 0x00000000004009f4 in main() at ref2.cpp:21 
+1

Я не думаю, что на C++ разрешены неназванные структуры. Во всяком случае, это выглядит как ужасный, ужасный код, который полностью нарушает дух C++ и OO. –

+0

Они, насколько я знаю. – q66

+0

@KerrekSB: вы формально правы, g ++ отказывается от кода с помощью '-pedantic'. Imageine имя там. – eudoxos

ответ

0

Сначала инициализируйте члены профсоюза, или это неопределенное поведение IIRC. Затем вы можете также инициировать ссылки на членов вашего профсоюза.

+0

Создание ссылки на унифицированные данные - это не UB, если ссылка не на самом деле доступна (исправьте меня, если я ошибаюсь, например, создание указателя на неинициализированный кусок памяти не UB; вы можете заполнить этот фрагмент памяти данными позже , перед использованием указателя) – eudoxos

+0

вы должны быть - но ваш код, похоже, нигде не заполняет его нигде. – q66

+0

Код просто определяет структуры данных и некоторые операции над ними, независимо от данных, которые он будет удерживать при использовании. – eudoxos

4

Это законный?

Нет, поскольку анонимные структуры не являются законными. Если вы его назовете, он будет вызывать неопределенное поведение , если толькоfoo правильно инициализирован (в частности, вы не можете прочитать x и y членов, если вы инициализировали data).

Как только я исправлю все это, какие другие проблемы вызовут это?

Ну, во-первых, наличие каких-либо ссылочных элементов препятствует генерации оператора присваивания. Это может или не может быть важно для вас. И тогда компилятор, созданный создателем копии, вас укусит: он просто слепо копирует все члены, заканчивая копией члена foo, а ссылочные члены ссылаются на foo объекта . Если этот исходный объект имеет более короткий срок службы, будут происходить плохие вещи. Возможно, вы захотите написать конструктор копирования или рассмотреть альтернативные проекты без ссылочных элементов.

+0

Спасибо за хороший ответ, вы, вероятно, на правильном пути. Я добавил экземпляр ctor и оператор присваивания классу, аналогичный тому, что у меня есть в коде, который сбой для меня. Предоставляет ли она правильную семантику для копирования? – eudoxos

+0

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

+0

Попробуем это и вернемся, если удастся его изолировать. – eudoxos