Форум программистов, компьютерный форум CyberForum.ru

std::vector<T>.push_back(T) - Error - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 29, средняя оценка - 4.93
goto
 Аватар для goto
76 / 34 / 4
Регистрация: 04.04.2011
Сообщений: 78
Записей в блоге: 1
14.08.2011, 08:45     std::vector<T>.push_back(T) - Error #1
Не пойму в чем дело, но при добавлении (CTextureManager :: load(const char* file)) в вектор – структуры, выскакивает ошибка...(в vector::size_type size() const) насколько мне известно push_back(T) делает копию помещаемого объекта и помешает его в вектор и вектор расширяется динамически. Привожу связанную с ошибкой часть кода, в чем может быть проблема?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
typedef struct tagTEXTURE
{
    unsigned int TexID;
    unsigned int w;
    unsigned int h;
 
} TEXTURE, *PTEXTURE;
 
class CTextureManager 
{
    typedef std::vector<TEXTURE>::iterator tex_map_iterator;
    typedef std::vector<std::string>::iterator tex_map_name_iterator;
    
    std::vector<TEXTURE> tex_map;
    std::vector<std::string> tex_map_name;
    
public:
    
    GLuint load(const char* file);
    
    TEXTURE* get_texture(const char* file);
    TEXTURE* get_texture(const GLuint id);
    
    //bool load_list();
    void cleanup();
    
};
 
// cpp
GLuint CTextureManager :: load(const char* file) 
{ 
    TEXTURE t = {};
    if (isFileExist(file)) 
    {
        
        if (LoadTextureFromFile(file, &t )) 
        {
            tex_map.push_back(t); //<-- ERROR!
            tex_map_name.push_back(std::string(file));
            return t.TexID;
        }
        else 
        {
            return GL_ERR;
        }
    }
    
    return GL_ERR;
};
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
14.08.2011, 09:28     std::vector<T>.push_back(T) - Error #2
goto, дык ошибка-то какая?
Bers
Заблокирован
14.08.2011, 09:50     std::vector<T>.push_back(T) - Error #3
goto, объекты, с которыми работают контейнеры стл, должны удовлетворять неким требованиям. Например, иметь копирующие конструкторы.

Может быть в этом дело?

/зы Что бы разобраться с ошибками, всегда указывайте, что пишет компилятор.
goto
 Аватар для goto
76 / 34 / 4
Регистрация: 04.04.2011
Сообщений: 78
Записей в блоге: 1
14.08.2011, 10:02  [ТС]     std::vector<T>.push_back(T) - Error #4
дык, я комментом место ошибки пометил, вот)
C++
1
tex_map.push_back(t); //<-- ERROR!
и само сообщение...

Не по теме:

Unhandled exception at 0x00444c96 in gt.exe: 0xC0000005: Access violation reading location 0xcdcdcdd1.



p.s. а оператор копирования обязательно свой определять для stl::vector? Компилятор должен же по умолчанию сгенерировать, если его нет, может в этом проблема.
Bers
Заблокирован
14.08.2011, 10:39     std::vector<T>.push_back(T) - Error #5
Цитата Сообщение от goto Посмотреть сообщение
p.s. а оператор копирования обязательно свой определять для stl::vector? Компилятор должен же по умолчанию сгенерировать, если его нет, может в этом проблема.
Есть вероятность, что он генерит нечто, не то, что нужно.
Особенно, если структура содержит какие то нетривиальные данные (поля-данные не POD объекты, указатели, и тп)

У меня однажды был случай, тоже с вектором, программа падала в каких то дебрях.
Оказалось, что ИмяКласса( ИмяКласса &ИсточникДанных); // это нефига не конструктор копирования.

Правильный конструктор копирования получается вот так:
ИмяКласса( const ИмяКласса &ИсточникДанных); //забыл указать ключевое слово const

В итоге, компилятор действительно генерил дефолтный конструктор копирования, и данные копировались как то видимо не так. Ошибку несколько часов вылавливал)

В вашем случае хочется взглянуть на код самой структуры.

Ошибка, которую выводит компилятор можно понимать так: нечто использует неправомерное чтение памяти, что приводит к "неопределённому поведению".

/зы один из способов отловить подобный тип ошибок - выполнить для данных (в вашем случае для структуры) все контракты контейнера.
То бишь, ручками определить копирующий конструктор, operator==, operator!=
Если ошибка не исчезнет - значит, она не связана с нарушением контрактов с контейнером. И нужно искать дальше...
goto
 Аватар для goto
76 / 34 / 4
Регистрация: 04.04.2011
Сообщений: 78
Записей в блоге: 1
14.08.2011, 11:44  [ТС]     std::vector<T>.push_back(T) - Error #6
В вашем случае хочется взглянуть на код самой структуры.
первый варинт был такой...
C++
1
2
3
4
5
6
7
typedef struct tagTEXTURE
{
        unsigned int TexID;
        unsigned int w;
        unsigned int h;
 
} TEXTURE, *PTEXTURE;
второй с конструктором копирования и оператором присвоения
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
typedef class tagTEXTURE
{
public:
    unsigned int TexID;
    unsigned int w;
    unsigned int h;
    
    // Конструктор поумолчан.
    tagTEXTURE() 
    {
        TexID = w = h = 0;
    };
    
    // Конструктор копирования
    tagTEXTURE(const tagTEXTURE& src) 
    {
        TexID = src.TexID;
        w = src.w;
        h = src.h;
    };
    
    // Оператор копирования
    tagTEXTURE& operator=(const tagTEXTURE& rhs)
    {
        if (this == &rhs)
            return *this;
        
        w = rhs.w;
        h = rhs.h;
        TexID = rhs.TexID;
        return *this;
    };
    
} TEXTURE, *PTEXTURE;
но после продолжительных ковыряний в коде выяснилось, что ошибка была совсем в другом месте, всему виной было отсутвие - texture_manager = new CTextureManager(); в нужном месте.))

C++
1
2
3
4
5
6
7
8
9
10
GLuint CGame :: SceneInit() 
{   
    texture_manager = new CTextureManager(); // <-- Забыл первоначально сделать, это ))
    
    texture_manager->load("resouces\\fonts\\font16.tga");
    texture_manager->load("resouces\\fonts\\font24.tga");
    ...
    ...
 
}
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
14.08.2011, 12:23     std::vector<T>.push_back(T) - Error #7
Цитата Сообщение от Bers Посмотреть сообщение
Правильный конструктор копирования получается вот так:
ИмяКласса( const ИмяКласса &ИсточникДанных); //забыл указать ключевое слово const
Bers, а как же std::auto_ptr, ведь при его копироавнии, в исходном обьекте указатель обнуляется.
Из википедии:
Вид X& конструктора копирования используется когда необходимо изменить копируемый объект. Это довольно редкая ситуация, но она предусмотрена в стандартной библиотеке вызовом std::auto_ptr.
http://ru.wikipedia.org/wiki/%D0%9A%...BD%D0%B8%D1%8F
Bers
Заблокирован
14.08.2011, 12:27     std::vector<T>.push_back(T) - Error #8
Net_Wanderer, тем не менее, если клиенту требуется конструктор копирования с константой, а в наличии его нет, компилятор сгенерит дефолтный.
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
14.08.2011, 13:02     std::vector<T>.push_back(T) - Error #9
Цитата Сообщение от Bers Посмотреть сообщение
Net_Wanderer, тем не менее, если клиенту требуется конструктор копирования с константой, а в наличии его нет, компилятор сгенерит дефолтный.
Хмм.. У меня MSVS на такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
class A {
public:
    A(int _n = 0) {n = _n;}
    A(A &rhs) {n = rhs.n;}
        int get_num(void) const {return n;}
        void set_num(const int _n) {n = _n;}
private:
        int n;
};
 
int main(void)
{
    const A ca(11);
    A a(ca);
     
    return 0;
}
выдает следующее: error C2558: class 'A' : no copy constructor available or copy constructor is declared 'explicit'

Добавлено через 4 минуты
А, ну получается то, так же как и с обычным конструктором. Если есть конструктор с параметрами, то дефолтный, компилятор генерировать не будет..
Bers
Заблокирован
14.08.2011, 13:46     std::vector<T>.push_back(T) - Error #10
Цитата Сообщение от Net_Wanderer Посмотреть сообщение
выдает следующее: error C2558: class 'A' : no copy constructor available or copy constructor is declared 'explicit'
Я точно не знаю. Но у меня есть подозрение, что

A(A &rhs) {n = rhs.n;} //не является копирующим конструктором, потому что клиенты ожидают что будит конструктор с константой.

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

Может быть я и ошибаюсь.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
14.08.2011, 13:53     std::vector<T>.push_back(T) - Error #11
Цитата Сообщение от Bers Посмотреть сообщение
Я точно не знаю. Но у меня есть подозрение, что
ну дак да - тут нарушение доступа - ca есть const объект, A требует неконстантного
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
14.08.2011, 14:05     std::vector<T>.push_back(T) - Error #12
Цитата Сообщение от Bers Посмотреть сообщение
Я точно не знаю. Но у меня есть подозрение, что
A(A &rhs) {n = rhs.n;} //не является копирующим конструктором, потому что клиенты ожидают что будит конструктор с константой.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
 
class A {
public:
    A(int _n = 0) {n = _n;}
    A(A &rhs)
    {
        n = rhs.n;
        std::cout << "copy constructor...\n";
    }
    int get_num(void) const {return n;}
    void set_num(const int _n) {n = _n;}
private:
    int n;
};
 
void foo(A a)
{
    a.set_num(1138);
}
 
int main(void)
{
    A aobj;
 
    foo(aobj);  
     
    return 0;
}
Обьект передается в foo по значению, вызвается конструктор копирования, сообщение выводится
Сыроежка
Заблокирован
14.08.2011, 16:42     std::vector<T>.push_back(T) - Error #13
Цитата Сообщение от Net_Wanderer Посмотреть сообщение
Хмм.. У меня MSVS на такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
class A {
public:
    A(int _n = 0) {n = _n;}
    A(A &rhs) {n = rhs.n;}
        int get_num(void) const {return n;}
        void set_num(const int _n) {n = _n;}
private:
        int n;
};
 
int main(void)
{
    const A ca(11);
    A a(ca);
     
    return 0;
}
выдает следующее: error C2558: class 'A' : no copy constructor available or copy constructor is declared 'explicit'

Добавлено через 4 минуты
А, ну получается то, так же как и с обычным конструктором. Если есть конструктор с параметрами, то дефолтный, компилятор генерировать не будет..

У вас выдает ошибку, потому что вы пытаетесь построить объект класса на основе константного объекта, а конструктора, который получает ссылку на константный объект у вас нет. То есть вам следовало бы объявить конструктор копирования следующим образом

C++
1
A(const A &rhs) {n = rhs.n;}
Либо вообще не объявлять констатные объеукты своего класса. Но тогда у вас будут проблемы с временными объяктами.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
Я точно не знаю. Но у меня есть подозрение, что

A(A &rhs) {n = rhs.n;} //не является копирующим конструктором, потому что клиенты ожидают что будит конструктор с константой.

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

Может быть я и ошибаюсь.
Не надо подозрений! Нужно точно знать, что это является конструктором копирования. Другое дело, что этот конструктор копирования не может работать с констатными объектами.

Добавлено через 4 минуты
Цитата Сообщение от Net_Wanderer Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
 
class A {
public:
    A(int _n = 0) {n = _n;}
    A(A &rhs)
    {
        n = rhs.n;
        std::cout << "copy constructor...\n";
    }
    int get_num(void) const {return n;}
    void set_num(const int _n) {n = _n;}
private:
    int n;
};
 
void foo(A a)
{
    a.set_num(1138);
}
 
int main(void)
{
    A aobj;
 
    foo(aobj);  
     
    return 0;
}
Обьект передается в foo по значению, вызвается конструктор копирования, сообщение выводится
Дело в том, что аргументом вашей функции является выражение, то есть rvalue, а оно должно связываться с константной ссылкой, когда используется для формирования значения параметра функции.
Bers
Заблокирован
14.08.2011, 17:32     std::vector<T>.push_back(T) - Error #14
Цитата Сообщение от Сыроежка Посмотреть сообщение
Не надо подозрений! Нужно точно знать, что это является конструктором копирования. Другое дело, что этот конструктор копирования не может работать с констатными объектами.
Благодарю.

Тогда ответьте мне, правильно ли я понял:

1. Если у класса отсутствует явный копирующий конструктор, то компилятор сам сгенерит дефолтный конструктор вида: ИмяКласса( const ИмяКласс& ИсточникДанных);

То бишь, источник данных будит константным, а не обычным?

2. Если у класса присутствует копирующий конструктор (не важно с константным источником данных, или нет), то никаких дефолтных конструкторов компилятор генерить не будит.

Таким образом, если не определён конструктор с константой, то ругаться будит вектор.
А если не определён конструктор с не_константой, то ругаться будит ауто_птр?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.08.2011, 17:37     std::vector<T>.push_back(T) - Error
Еще ссылки по теме:

Как изменять размер std::vector<std::vector>? C++
C++ Теряю ссылку на элемент в std::vector после того, как делаю push_back следующего элемента
Error C2440 std::vector<_Ty> C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Сыроежка
Заблокирован
14.08.2011, 17:37     std::vector<T>.push_back(T) - Error #15
Цитата Сообщение от Bers Посмотреть сообщение
Благодарю.

Тогда ответьте мне, правильно ли я понял:

1. Если у класса отсутствует явный копирующий конструктор, то компилятор сам сгенерит дефолтный конструктор вида: ИмяКласса( const ИмяКласс& ИсточникДанных);

То бишь, источник данных будит константным, а не обычным?

2. Если у класса присутствует копирующий конструктор (не важно с константным источником данных, или нет), то никаких дефолтных конструкторов компилятор генерить не будит.

Таким образом, если не определён конструктор с константой, то ругаться будит вектор.
А если не определён конструктор с не_константой, то ругаться будит ауто_птр?
Да, вы правильно понимаете, что по умолчанию создается конструктор копирования ClassName( const ClassName & ). Он является inline и public функцией. Ежели вы объявили свой конструктор копирования, то он и будет использоваться. Конструктор копирования можно объявить, как конструктор, первым параметром которого является

const ClassName &
ClassName &
volatile ClassName &
const volatile ClassName &

При этом все другие параметры должны иметь аргументы, заданные по умолчанию.
Yandex
Объявления
14.08.2011, 17:37     std::vector<T>.push_back(T) - Error
Ответ Создать тему
Опции темы

Текущее время: 16:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru