Where are const objects stored - c++

I do understand that functions should not return references to automatic variables.
However I just wanted to understand where constant objects are stored i.e if it is stored in the memory section along with static global variables .
Here is the code on Visual studio 8 . It looks like const objects are stored as auto variables. Am i assuming things right or is it implementation specific or does it depend on whether the constructor is trivial ?
Would be really great if someone could explain why each of these cases behave the way they do.
//here i'm intentionally returning a ptr to local const ptr hope the syntax is right
const char* const* get_const_char_ptr() {
const char * const ptr = "downontheupside";
return &ptr;
}
const int& get_const_int() {
const int magic_number = 20;
return magic_number;
}
const string& get_const_string() {
const string str("superunknown");
return str;
}
const string* get_const_string_ptr() {
const string str("louderthanlove");
return &str;
}
int main() {
//case1
const int &i = get_const_int();
cout<<"case1:"<<i<<endl;
//case 2
const char * const* c =get_const_char_ptr();
cout<<"case2:"<<*c<<endl;
//case3
const string &str = get_const_string();
//this crashes
//cout<<"case3:"<<str<<endl;
return 1;
}

const does not change where things are stored it's a keyword to tell the compiler to prevent variables or functions from modifying things. Example:
std::string myNormalStr("Hello");
const std::string myConstStr("Don't Change Me");
myNormalStr = myConstStr; // this is ok
myConstStr = myNormalStr; // this will give you a compile error
That's a super simplistic example but the same thing applies to const objects which are passed into functions, returned from functions, or if the function itself is const.
Here's a great article by Herb Sutter on all the correct ways to use the const keyword.
Edit:
Currently there is almost no reason to use the auto keyword as everything is implicitly auto within it's scope. This keyword is a storage class specifier for an automatic variable.
However the auto keyword is changing as part of the new C++ standard in progress but is supported already by Visual Studio 2010 and some other compilers in it's new glorious form. It can be used like so in C++0x:
std::vector<int> numbers;
for (std::vector<int>::const_iterator itr(numbers.begin());
itr != numbers.end(); ++itr)
{
// do something with each iterated element
}
// compiler auto deduces from rvalue
// and determines that you want a
// std::vector<int>::const_iterator type
for (auto itr = numbers.cbegin();
itr != numbers.cend(); ++itr)
{
// do something with each iterated element
}

Constant objects allocated within a function are just like any other automatic variable; they just have const types. Global (and class-static) variables are slightly different: some constants can be placed in read-only parts of the executable file and then just copied into memory. That is used for things like string and integer constants; I do not believe it is used for anything with a nontrivial constructor.

Absolutely everything about where something is stored is implementation specific. Never forget that. With that caveat, here are some typical rules.
Automatic variables are either stored on the stack or in a register. Doesn't matter if they're const or not.
Static variables are stored in program memory. There may be multiple blocks of program memory, some read-only and some not. Declaring a variable const may affect which block something is stored in.
Variables allocated with new will be on the heap. Doesn't matter if it's const or not.

Related

How to pass an array of constexpr strings as an argument?

I have a file which contains arrays of strings representing some icons.
static constexpr char icons1[2][40] = {
"icon1_A", "icon1_B"
};
static constexpr char icons2[3][30] = {
"icon22_A", "icon2_B", "icons2_C"
};
Then I have a class that wants to be initialized with a reference to these icons.
class Display {
public:
Display(const char ** _icons) : icons(_icons), current_icon(0) {}
void print_next_icon() {
std::cout << icons[++current_icon] << std::endl;
}
private:
const char **icons;
size_t current_icon;
}
I am getting a compiler error when I try to initialize the Display class by passing it the constexpr icons:
Display i1(icons1);
Display i2(icons2);
I've tried casting it to const char**, but the compiler complains that the cast removes attributes.
The declaration here is needlessly complicated. Try and keep it simple:
static const char* icons1[] = {
"icon1_A", "icon1_B"
};
If you're passing these in as arguments and you need to know exactly how many there are it helps to have some kind of terminator:
static const char* icons1[] = {
"icon1_A", "icon1_B", nullptr
};
Where you can iterate through this list until you hit nullptr and then stop.
constexpr is used for, not surprisingly, const expressions, as in more complex expressions with operators in them and/or functions that you want to evaluate. It's not necessary here since nothing exotic is going on, this is a straight-forward const declaration.
What's worth noting here is that the memory layout of char** and char[3][40] are completely different. In the first case you have an array of pointers, where those pointers refer to arbitrary memory locations, and in the second you have what is effectively a contiguous chunk of 120 bytes, no pointers at all. This cannot be recast to the other form, it requires creating a new array of pointers.
That being said, your function assumes that these pointers will have an indefinite lifespan, which can be risky. It's almost always safer to use std::string, as in std::vector<std::string> to pass these around.

Initializing a Struct's variable const char* const* with C++

I am trying to solve a coding question that requires the results be returned using a given struct. The struct is defined as:
struct Answer
{
const char* const* lastNames;
unsigned numberOfPeople;
}
Where the lastNames is a pointer to last names that are each terminated by a non-alpha char. I can not seem to find any way to convert the vector of strings that I am using to compile all the last names into a variable that I can assign to lastNames. I have tried making a single string with all the last names and assigning it with c_str() like so:
Ans->lastName = allNames.c_str(); but this gives me an error. Due to the limitations of the question I am unable to change the struct variable to anything else. How can I assign a string to a const char* const*
The structure being used effectively uses a C-style approach to defining a variable sized array of pointers to char (with const sprinkled over it). You’ll need storage for both the array of char const* as well as the entities pointed to. Here is how you could build it from a std::vector<std::string>:
std::vector<std::string> strings = somehow_compute_the_strings();
std::vector<char const*> array;
for (std::string const& s: strings) {
array.push_back(s.c_str());
}
Answer answer = { array.data(), array.size() };
Of course, you can’t return answer without the pointer inside pointing to stale data: you’d need to keep the two std::vectors alive. Potentially these two objects could be made members of an object the function is called on. To actually return an object of type Answer without a place to hold on to the std::vectors you could allocate the relevant entities and accept that the result will yield a memory leak unless the caller can clean the result up.
You can't just cast stuff. struct Answer is expecting a char**, so you are going to have to build it and keep it valid as long as the struct Answer is in use. At least they were kind enough to let us know they don't intend to modify it or mess with cleaning up the memory, since it takes "const char * const *".
#include <iostream>
#include <vector>
#include <string>
#include <assert.h>
typedef std::vector<std::string> VectorOfStrings_type;
struct Answer
{
const char* const* lastNames;
unsigned numberOfPeople;
};
class AnswerWrapper
{
private:
// construct and maintain memory so the pointers in the Answer struct will be valid
char ** lastNames;
unsigned int numberOfPeople;
public:
AnswerWrapper(const VectorOfStrings_type &input){
numberOfPeople = input.size();
// create the array of pointers
lastNames = static_cast<char**>(
malloc(numberOfPeople * sizeof(char*))
);
// create each string
for (unsigned int i = 0; i < numberOfPeople; ++i){
const std::string &name = input[i];
// allocate space
lastNames[i] = static_cast<char*>(
malloc(name.size() + 1)
);
// copy string
strncpy(lastNames[i], name.data(), name.size());
// add null terminator
lastNames[i][name.size()] = '\0';
}
}
operator Answer (){
return Answer{ lastNames, numberOfPeople };
}
~AnswerWrapper(){
// critcally important, left as an exercise
assert(0);
}
};
void SomeFunctionWhichUsesAnswer(Answer a){
// presumably you have some legacy C code here
// but here's a quick and easy demo
for (unsigned int i = 0; i < a.numberOfPeople; ++i)
std::cout << a.lastNames[i] << std::endl;
}
int main() {
// Here is your vector of strings
VectorOfStrings_type myData { "custom formatted data goes here", "and more here", "and again" };
// You must construct a buffer for the "Answer" type, which must remain in scope
AnswerWrapper temp{ myData };
// AnswerWrapper is currently in scope, so inside this function, the pointers will be valid
SomeFunctionWhichUsesAnswer(temp);
}
Also, I noticed that the strings in Answer are not referred to as null terminated. That is a separate issue you can take care of.
A const member variable can only be assigned in the constructor.
if you can add to the struct, define a constructor, and use the : lastname(value) syntax; or use the struct Answer myVar{value,number}; initialization, right where you declare your instance.
Another - ugly, dangerous, and frowned upon - alternative is a cast: (char**) lastname = value;, or in C++ syntax reinterpret_cast<char**>(lastname) = value.
If someone is teaching you either of those approaches, change the teacher.

How to get pointer to string's data in a vector of strings? [duplicate]

This question already has answers here:
C++11 "auto" semantics
(3 answers)
Closed 4 years ago.
I have a vector of strings as my primary data container. However, in order to interoperate with a C library, I need to be able to view these strings as character data pointers (i.e. const char*). This sounds simple enough, so I wrote a helper class like this:
class strvecAccessor {
const std::vector<std::string>& names;
public:
strvecAccessor(const std::vector<std::string>& a) : names(a) {}
size_t size() const {
return names.size();
}
const char* item(size_t i) {
auto name = names[i];
return name.data();
}
};
This accessor class is short-lived. It serves as a wrapper around an existing vector of strings, which is guaranteed to not be modified or go out-of-scope during the lifespan of this class. An example of how this class can be used is the following:
void test(strvecAccessor& arr) {
for (size_t i = 0; i < arr.size(); ++i) {
printf("%s\n", arr.item(i));
}
}
But there is a bug in this code, which manifests itself only when I compile it in --coverage -O0 mode, and only on Unix machine (I compile with CLang 6.0.0 in C++11 compatibility mode). The bug is that the printed strings contain garbage.
I believe what happens is that the name variable in item() method is not a reference, but a copy of the i-th element of the array. It goes out-of-scope at the end of the item() function, at which point the pointer that was returned becomes dangling. Most of the time it is not noticeable since the pointer is used immediately, but in coverage mode it gets filled up with other data right after the call.
The problem disappears if I replace auto name = names[i]; with const std::string& name = names[i];. But I don't really understand why, and whether this actually solves the problem or just buries it deeper. So my question is: why the copy is being made in the original code; and how to protect myself against these kinds of errors in the future?
const char* item(size_t i) {
auto name = names[i];
return name.data();
}
Here, name is a local variable to the function item(), and you're returning an address to data that is owned by that local variable. When it goes out of scope (the item() function completes) name will be destroyed.
Since you're guaranteeing the lifetime of the underlying vector, try this instead:
const char* item(size_t i) {
return names[i].data();
}
This will be "safe", because vector::operator[] returns a reference to the stored data, and you don't make an extraneous copy into your name variable like in your original.

const char* getting modified after assigning to char*

int FunctionName(const char *pValueName, const char *pValueData, long iMaxValueSize)
{
char *pDataToStore = const_cast<char *>(pValueData);
int iActualSiz = ProcessData(pDataToStore, iMaxValueSize);
...
...
}
In the upper code snippet ProcessData() function modifies the char*, which it receives as parameter. Now even after assigning pValueData into pDataToStore, after ProcessData() get executed, value of pValueData is being same as pDataToStore.
My aim is to keep intact value of pValueData which is being passed as const char*
My aim is to keep intact value of pValueData which is being passed as
const char*
That's impossible. Passing via const means it cannot be modified, except when it was originally not constant.
Example:
char *ptr1 = new char[100]; // not const
char *ptr2 = new char[100]; // not const
int i = FunctionName(ptr1, ptr2, 123);
In this case, you could technically keep the const_cast. But what for? Just change your function parameters to take char *:
int FunctionName(char *pValueName, char *pValueData, long iMaxValueSize)
{
int iActualSiz = ProcessData(pValueData, iMaxValueSize);
// ...
}
However, you most likely want to be able to pass constant strings. For example string literals:
int i = FunctionName("name", "data", 123);
String literals are unmodifiable and thus require your function to take char const *. A later attempt to modify them causes undefined behaviour.
As you can see, the error is in the general architecture and code logic. You want to modify something and at the same time you do not want to allow to modify it.
The question is: What happens with your pDataToStore when ProcessData is done with it? Does the caller of FunctionName need to be aware of the modifications? Or is it just internal business of FunctionName?
If it's just internal business of FunctionName, then you can keep its signature intact and have ProcessData modify a copy of the passed data. Here is a simplified (not exception-safe, no error checks) example:
int FunctionName(const char *pValueName, const char *pValueData, long iMaxValueSize)
{
char *copy = new char[strlen(pValueData) + 1];
strcpy(copy, pValueData):
int iActualSiz = ProcessData(copy, iMaxValueSize);
// ...
delete[] copy;
}
The nice thing is that you can now massively improve the interface of FunctionName by hiding all the low-level pointer business. In fact, why use so many pointers at all when C++ standard classes can do all the work for you?
int FunctionName(std::string const &valueName, std::string const &valueData, long maxValueSize)
{
std::vector<char> copy(valueData.begin(), valueData.end());
int actualSize = ProcessData(&copy[0], maxValueSize);
// ...
// no more delete[] needed here
}
The std::vector<char> automatically allocates enough memory to hold a copy of valueData, and performs the copy. It fully automatically frees the memory when it is no longer needed, even if exceptions are thrown. And &copy[0] (which in C++11 can be written as copy.data()) is guaranteed to yield a pointer to the internally used data, so that low-level C functions can modify the vector's elements.
(I've also taken the chance to remove the Microsoft-style Hungarian Notation. It's a failed experiment from the 90s, and you've even used it incorrectly, supposing that a leading i is supposed to indicate an int.)
The bottom line is really:
If you need a const_cast anywhere in your code to make it compile, then somewhere else there is at least either one const missing or one too much. A const_cast always makes up for a mistake in another piece of code. It is always a workaround and never a solution designed up front.
Well I have solved the issue by creating the heap memory.
char *pDataToStore = new char[iMaxValueSize];
memcpy(pDataToStore, pValueData, iMaxValueSize*sizeof(char));
int iActualSiz = ProcessData(pDataToStore, iMaxValueSize);
...
....
delete []pDataToStore;
You have to make a difference between a const qualified type and a const qualified object.
The standard states in section 7.1.6.1: cv-qualifiers: (cv = const or volatile)
A pointer or reference to a cv-qualified type need not actually point
or refer to a cv-qualified object, but it is treated as if it does; a
const-qualified access path cannot be used to modify an object even if
the object referenced is a non-const object and can be modified
through some other access path.
If your pointer points to a non const object, the casting away will enable you to modifiy the objet, but as someone told, you are lying to the user of your function.
It your pointer points to a real const object (i.e. in const protected memory), the compiler will compile your code, but you might have a segmentation fault, typical for undefined behaviour.
Here an example, using the fact that "Ordinary string literal (...) has type “array of n const char”, where n is the size of the string (...)" (see standard, section 2.14.5):
char *my_realconst = "This is a real constant string"; // pointer does not claim that it points to const object
(*my_realconst)++; // Try to increment the first letter, will compile but will not run properly !!
So if your function ProcessData() is legacy code that is only reading the data but has forgotten to mention a const in the parameter list, your cast-away will work. If your function is however altering the data, it might work or it might fail, depending how the data poitned to was created !
So try to avoid casting const away if you are not 100% sure of what the effects will be ! Better clone your object the hard way creating a temporary object and copying the content.
I propose you a small template to handle these kind of issues easily:
template <typename T>
class Buffer {
size_t sz; // size
T* addr; // pointed
public:
Buffer(const T*source, size_t l) : sz(l), addr(new T[l]) { std::copy(source, source + l, addr); } // allocate and copy
~Buffer() { delete[]addr; } // destroy memory
operator T* () { return addr; } // convert to pointer
};
You may use your existing code almost as is:
Buffer<char> pDataToStore(pValueData, iMaxValueSize); // create the automatic buffer
int iActualSiz = ProcessData(pDataToStore, iMaxValueSize); // automatic use of pointer to buffer
cout << "modified copy: " << pDataToStore << endl;
cout << "original: " << pValueData << endl;
The buffer will be automatically released once pDataToStore is no longer in scope.
If you have similar issues with wchar_t buffers or anything else, it will work as well.
For explanations on the evil of casting away const, see my other answer

What is more efficient: pass parameter by pointer or by value?

What is more efficient: Call by pointer or by value? I think it is call by pointer, because passing a pointer to a variable does not use as much memory as creating a copy of a variable. Am I wrong?
main(){
int a, b;
a = 10;
b = 5;
gcf(&a, &b);
return 0;
}
int gcf(int* c, int* d){
int val1=*c;
int val2=*d;
//...
}
In nearly all code, as long as we're dealing with small/simple objects, the overhead of copying the object, vs. passing it as a pointer or reference is pretty small.
Obviously, if we make a std::string with a large chunk of text in it, it will take quite some time to copy it, relative to just passing a reference.
However, the primary objecting ANY TIME when writing code is to focus on correctness. If you have "large" objects, then use const Type &val if the value is not being modified - that way, you can't accidentally modify it. If the object is to be modified, then you NEED to use a reference or pointer to get the updates back to the caller of the function.
It is entirely possible to make code that runs noticeably slower with a reference than with a value. I was once looking into the performance of some code that we were working on, and found a function that looked something like this:
void SomeClass::FindThing(int &thing)
{
for(thing = 0; someVector[thing] != 42; thing++)
;
}
It really looks rather innocent, but since each update of thing means an indirect memory access [at least in the compiler we used, which was certainly not "rubbish"], it was taking quite a lot of time out of the entire process [it was also called twice as much as necessary].
I rewrote it as:
void SomeClass::FindThing(int &thing)
{
for(int i = 0; someVector[i] != 42; i++)
;
thing = i;
}
And the function ran about 4x faster. Taking out the second, unnecessary call, as well, and we ended up with about 30% faster runtime. This was in a "fonts benchmark", and this was one out of a several dozen functions involved in the "draw fonts to screen". It's scary how a simple, innocent looking function can make a BIG difference to performance.
For types smaller than the size of a pointer (e.g. int), passing by value is more efficient.
For types bigger than the size of a pointer (e.g. most struct or class instances), passing by reference is probably more efficient (only "probably" because on top of the cost of passing the parameter, potentially constructing an object, you incur the cost of dereferencing your parameter every time you use it).
More details about passing-by-value vs. passing-by-reference can be found in this question. More details about reference vs. pointer arguments can be found in that question.
In your example of code snippet
main(){
int a, b;
a = 10;
b = 5;
}
int gcf(int* c, int* d){
int rem;
int val1=*c;
int val2=*d;
//...
}
there is no any sense to pass variables a and b to the function indirectly using pointers if you are not going to change them. In this case the code is ineffective because that to get values of *c and *d the compiler will need to generate more instructions.
And you are wrong saying that
passing a pointer to a variable does not use as much memory as
creating a copy of a variable. Am I wrong?
Usually pointers are equal to or even larger than the size of type int. For exaple in a 64-bit system sizeof( int ) can be equal to 4 while sizeof( int * ) can be equal to 8.
There is a sense to pass an object indirectly by pointers (usually in C programs) when the size of the object is much larger than the size of the pointer.
In C++ instead of pointers usually references are used.
For example
#include <iostream>
#include <string>
inline void print_reverse( const std::string &s )
{
std::cout << std::string( s.rbegin(), s.rend() ) << std::endl;
}
int main()
{
std::string s( "Hello World" );
print_reverse( s );
}
Here const std::string &s defined reference to an object of type std::string.