G21
G21

Reputation: 1345

How to create an instance of a struct in C++?

The issue is an "Access violation writing location 0x00000000" error message right after I initialize the bk variable to NULL. My guess is I should reserve memory space in advance to assign NULL ( something like Book bk = new Book(); ) but I have not been able to figure out how to do it in C++ till now.

Book.h

#ifndef Book_H
#define Book_H

struct _book;
typedef _book* Book;

Book CreateBook(unsigned int pageNum);

Book.cpp

#include "Book.h"
#include <iostream>

#ifndef Book_CPP
#define Book_CPP

using namespace std;

struct _book
{
    int pageNum;
};

Book CreateBook( unsigned int pageNum){

    Book bk = NULL; 

    bk->pageNum = pageNum;

    return bk;
};

Upvotes: 21

Views: 115775

Answers (8)

Manjunath Bhadrannavar
Manjunath Bhadrannavar

Reputation: 163

but if you dont want to create a variable from heap then, you can directly create and return this way

bk = _book{any_data_that_you_want_to_insert};
// ...
return bk;

Upvotes: 0

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275896

Book.h

#ifndef Book_H
#define Book_H

// why not put the layout here?    
struct Book
{
    int pageNum;
};
Book CreateBook(unsigned int pageNum);

#endif

Book.cpp

#include "Book.h"

// no #define guards
// do not using namespace std;, it is a bad habit

Book CreateBook( unsigned int pageNum){
  Book bk;
  bk.pageNum = pageNum;
  return bk;
};

This is the simplest solution. Books are actual values, and can be copied and moved around and the like.

If you need the opacity of an abstract type, only then should you deal with pointers. When you do deal with pointers, hiding them behind a typedef is a bad idea: pointers mean resource management, so it should be obvious that you are using them.

The pointer-based version:

#ifndef Book_H
#define Book_H

// why not put the layout here?    
struct Book;
Book* CreateBook(unsigned int pageNum);

#endif

* Book.cpp *

#include "Book.h"

// no #define guards
// do not using namespace std;, it is a bad habit

Book* CreateBook( unsigned int pageNum){
  Book* bk = new Book;
  bk->pageNum = pageNum;
  return bk;
};

but, if you are creating stuff, you should probably create smart pointers:

#include <memory>
std::shared_ptr<Book> CreateBook( unsigned int pageNum){
  std::shared_ptr<Book> bk( new Book );
  bk->pageNum = pageNum;
  return bk;
};

Upvotes: 2

bstamour
bstamour

Reputation: 7776

You're assigning bk to NULL and then trying to access a member of it. That's the same as a null pointer in Java, and what you're doing would typically raise a NullPointerException (thanks from the comments). If you want to create a pointer to your struct, you need to use operator new:

bk = new _book;
// ...
return bk;

and then make sure you call delete on the pointer when you're done with it.

I would advise against using pointers here, though. Unlike other languages, C++ lets you create objects by value. It also allows for references and pointers, but only use pointers when you absolutely must. If you simply want to create a book object with a given pageNum, you should create a constructor while you're at it:

struct _book {
    int pageNum;
    _book(int n) : pageNum(n) // Create an object of type _book.
    {
    }
};

and then you can invoke it like

_book myBook(5); // myBook.pageNum == 5

If you're new to C++, please get yourself a good book on it. It's not just a low-level language, and it's also not just an OOP language. It's a multi-paradigm swiss army knife language.

Upvotes: 26

qxixp
qxixp

Reputation: 131

This is what you need:

Book CreateBook( unsigned int pageNum){

    Book bk = new _book();

    bk->pageNum = pageNum;

    return bk;
}

your bk was null and you cannot access pageNum when the pointer is null.

And don't forget to call delete on bk when you are done using it.

Upvotes: 4

SigTerm
SigTerm

Reputation: 26439

struct Book{
    int pageNum;    
};

Book* createBook(int pageNum){
    Book *result = new Book;
    result->pageNum = pageNum;
    return result;
}

int main(int argc, char** argv){
    Book book;
    book.pageNum = 0;
    return 0;
}

or

struct Book{
    int pageNum;    
    Book(int pageNum_ = 0)
    :pageNum(pageNum_){
    }
};

Book* createBook(int pageNum){
    return new Book(pageNum);
}

int main(int argc, char** argv){
    Book book(0);
    return 0;
}

Upvotes: 0

Simple
Simple

Reputation: 14420

There are a few mistakes in your code.

  1. You need to put an #endif at the end of your header file.
  2. You need to place a semicolon at the end of struct, class and union definitions (after the closing brace).
  3. You shouldn't be using pointers at all in such a simple use case.

Example:

Book.h

#ifndef BOOK_H
#define BOOK_H

struct Book
{
    int pageNum;
};

Book CreateBook(int pageNum);

#endif

Book.cpp

#include "Book.h"

Book CreateBook(int pageNum)
{
    Book bk;

    bk.pageNum = pageNum;

    return bk;
}

You don't need the CreateBook function anyway but I left it in anyway.

Upvotes: -1

iseletsky
iseletsky

Reputation: 653

Why are you doing the typedefing? It can be good practice in some cases for some reason I guess.

In case you didn't know, you could also write just:

_book book;

Now book is allocated statically on the stack instead of dynamically in the heap. It'll get destroyed automatically when the variable goes out of scope just like int or double, etc...

This is useful sometimes if you want to avoid the overhead or work of allocating memory for something really simple. It was weird for me to go into Java and have to say,

vec3 position = new Vec3(0.0, 1.0, 5.0);

instead of just saying

vec3 position(0.0, 1.0, 5.0);

like you would in C++.

Upvotes: 0

P0W
P0W

Reputation: 47844

In

Book bk;

bk is a pointer

Allocate memory for it first

Book bk* = new _book();

And then do

bk->pageNum = pageNum;

Also don't forget to free the memory using

delete bk;

Upvotes: 0

Related Questions