1

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:

  • the price level
  • another std::list with all orders at that price. (Orders)

An Order is a struct with:

  • userid
  • quantity

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?

jmary
  • 257
  • 4
  • 11

4 Answers4

5

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.

freakish
  • 54,167
  • 9
  • 132
  • 169
  • I use list because I can insert elements without having internally to move all precedent records, and I won't need to access an element directly by its position ... (Got this from Scitt Meyer book, effective STL). Please let me know. Please tell me if this wrong. Thanks, for answer, I'm presently trying it. – jmary May 03 '17 at 08:32
  • Use `vector` unless you have a good reason to use another container! – Ajay May 03 '17 at 08:50
  • @jmary You may find that `std::vector` is still more efficient. Unless you are dealing with huge lists. You say you are not going to access an element by its position. Are you going to iterate over the list? Vectors iterate waaaaay faster then lists (one memory block, no pointer dereferencing + cpu prefetcher). Anyway, measure it. – freakish May 03 '17 at 08:51
  • The list is likely to have some million entries. The list of bids allows me to group orders for a given price so that I can sum up total quantity a summing on all orders (i need to parse them all anyway) and know quickly the sum and orders involved. My insertion cost into the bidList is low comparing to moving all bids with superior price (if i was using vectors), especially if i have millions to move at each insertion. – jmary May 03 '17 at 09:01
  • @jmary If you can predict more or less how many bids are there then you can always allocate needed size beforehand via `vector.reserve(total_amount_of_bids)`. This will save you from unnecessary copies and still give you needed performance. Otherwise `std::list` might be better but you should definitely measure it first. Note that summing over a list is an iteratotion as well. Will definitely be slower then over a vector. – freakish May 03 '17 at 09:26
1

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());
Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40
1

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.

Markus Mayr
  • 4,038
  • 1
  • 20
  • 42
0

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;
}
jmary
  • 257
  • 4
  • 11