jmary
jmary

Reputation: 280

C++ std::list with struct containing list with struct

I'm new to C++ (I did C before but never C++) I believe I have syntax problem.

I want to sort some orders by price level into a list. So my list has positions with inside:

An Order is a struct with:

So I ended with :

#include<iostream>
#include<list>
using namespace std;

typedef struct Order {
  int userid;
  int qty;
} Order;

typedef struct Bid {
  int price;
  list<Order> Orders;
} Bid;

typedef list<Bid> bids;

int main(void)
{
  bids list;
  Order order_to_insert;

  list.begin();
  list.front().price = 13000;

  order_to_insert.userid = 3;
  order_to_insert.qty = 20;


  list.front().Orders.begin();
  list.front().Orders.front().userid =3;
  list.front().Orders.front().qty = 20;
  // list.front().Orders.front() =  order_to_insert;  // compiles even if i uncomment this.


  cout << "Liste : " << list.front().price << endl;
  cout <<  list.front().Orders.front().qty  << endl;

  return 0;
}    

The most intuitive way initially was to use the commented line, it compiles but gives seg fault.

I commented to assign values to fields directly and it seg fault also.

What is the proper way to do that?

Upvotes: 1

Views: 1717

Answers (4)

freakish
freakish

Reputation: 56467

First of all this line list.begin(); and that line list.front().Orders.begin(); don't do anything. Remove them.

Now the main problem. Elements in lists don't appear automagically. Lists are empty when created. Have a look at this line:

list.front().price = 13000;

At that point your list is empty, there is no .front(). So its an undefined behaviour, probably the cause of the segfault.

This will do:

Bid bid;
list.push_back(bid);
list.front().price = 13000;
// or if C++11
list.emplace_back();
list.front().price = 13000;

The same goes for list.front().Orders.front() and every other line using .front().

Side note: You may want to use list.emplace_back instead of push_back. Also you may want to use std::vector instead of std::list. There are several performance advantages over a list and it should be used by default unless you really know that you need lists.

Upvotes: 5

jmary
jmary

Reputation: 280

Thanks guys for clear explanations and advises. I ended with the following working code :

#include <iostream>
#include <list>
using namespace std

typedef struct Order {
  int userid;
  int qty;
} Order;

typedef struct Bid {
  int price;
  list<Order> Orders;
} Bid;

typedef list<Bid> bids;

int main(void)
{
  Bid bid;
  bids bidList;
  Order order_to_insert;

  bidList.push_back(bid);
  bidList.front().price =13000;

  order_to_insert.userid = 3;
  order_to_insert.qty = 20;

  bidList.front().Orders.push_back(order_to_insert);
  bidList.front().Orders.front() = order_to_insert;

  cout << "Liste : " << bidList.front().price << endl;
  cout <<  bidList.front().Orders.front().move  << endl;

  return 0;
}

Upvotes: 0

Markus Mayr
Markus Mayr

Reputation: 4118

You do not insert elements into your list. std::list::front will return the first element of the list if it is non-empty, but behaviour is undefined if the list is empty.

std::list::begin returns an iterator to the first element, if the list is non-empty or the past-the-end iterator if the list is empty.

Use std::list::push_back to insert new elements into your list.

Upvotes: 1

Sander De Dycker
Sander De Dycker

Reputation: 16243

Calling front() on an empty list has undefined behavior. An empty list doesn't have a first item, so you shouldn't be trying to access it.

You can use push_back() eg. to add an item into the list, which you can then access and modify.

list.push_back(Bid());

Upvotes: 1

Related Questions