May this kind of rewrite of placement new compile? - c++

Background
I am cleaning up a legacy codebase by applying a coding guideline for the new statement.
There is code like auto x = new(ClassName); that I rewrite to auto x = new ClassName();. It's quite obvious that this is not a placement new and I don't need to think about it.
However, there's also code like auto x = new(ClassName)(argument); which looks much like a placement new. For now I blindly rewrote such code to auto x = new ClassName(argument); as well.
Question
Might there be a case where a real placement new like auto x = new(placement-params)(Type); is rewritten as auto x = new placement-params(Type); and it still compiles but changes the meaning of the program?

placement-params is not a type, it is a value.
Consider this code with a placement new:
int* buf = new int;
int* a = new(buf)(int);
If we remove parenthesis around buf, the compiler can easily detect buf is not a type.
int* a = new buf(int); // compile error
Even if we create a type named buf, by the name lookup rules, the name in the inner scope is found first:
class buf { // found second
buf(int) {}
};
int main() {
int *buf = new int; // found first
int* a = new buf(int); // compile error
return 0;
}
According to this answer, when type and value are in a same scope, the value is found first. For example:
class buf { // found second
buf(int) {}
};
int *buf = new int; // found first
int main() {
int *a = new buf(int); // compile error
return 0;
}

Related

A simple question about pointer assignment in c++ function

This is my code, after a = b; in the function, a is still nullptr....
int getBox(int *a) {
int *b = new int;
*b = 3;
a = b;
std::cout << *a;
}
int main() {
int *a = nullptr;
getBox(a);
std::cout << a;
}
I guess it's a very simple problem... Maybe I forgot too much about C++
I'm not sure what you're trying to do, but this row inside the getBox():
a=&b;
Doesn't actually change a in the main, you actually overrides the pointer(the copy that was made by the function), and make it point somewhere else.
You can do something like this(again, I don't see the point) :
int getBox(int ** a){
int *b = new int;
*b=3;
*a=b;
std::cout<<*a;
}
int main(){
int *a= nullptr;
getBox(&a);
std::cout<<a;
}
Let's assume there is some type T. Now here are 3 different kinds of functions:
void f(T a) { // pass by value (this is a copy of the 'a' in main)
a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(a);
// a is still something
}
void f(T &a) { // pass by reference (this is a reference to the 'a' in main)
a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(a);
// a is now something else
}
void f(T *a) { // pass by address (this is a pointer to the address the 'a' in main)
*a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(&a);
// a is now something else
}
Now you can apply this logic to any T you want, such as int, or int*, and the same rules will work. You can try this out with getBox and see the effect of each version, which should help you understand what's going on. Note that you are using the first version (pass by value), but for the result you are expecting, you should use the second version (pass by reference).
If you really want to change what a is pointing to, then you can think it this way maybe it will help to make it a bit easier to understand. A is an int pointer and the function getBox takes a reference that you can modify its value which is an int pointer.
void getBox(int* &a) {
int *b = new int;
*b = 3;
a = b;
std::cout << *a;
}
int main(){
int *a= nullptr;
getBox(a);
std::cout<< *a;
}
This will change the value of a, which is a new pointer value to b.
Yes of course, why should changing a in getBox change the value of a in main? If you think the answer is 'because it's a pointer' then I'm afraid you've misunderstood pointers.
Look at this code
int getBox(int a){
a=3;
std::cout<<a;
}
int main(){
int a= 0;
getBox(a);
std::cout<<a;
}
Setting a=3 in getBox has no effect on a in main. Your code is exactly the same, but for some reason because pointers are involved beginners often think it works differently. It doesn't.
You can however use pointers in this way to change what is being pointed at, that's the important thing, but changing the pointer itself doesn't work in the way you are expecting.
You probably only want to change to getBox(int * & a). You then pass a reference to the pointer a to the function instead of creating a copy of the pointer that points to the same address in your case NULL.

Can I really create a global variable with every declaration of a Type?

So I wrote this code and was kind of surprised when it compiled (I am using gcc version 5.1.0):
struct Mine
{
const int* ptr;
Mine(const int x)
: ptr([=]()
{
static const int n = x;
return &n;
}()
){}
};
Mine first = 12;
Mine second = 13;
The reason I am surprised is that each declaration of Mine creates a new "global" variable.
So here is the question:
Am I supposed to be allowed to do this?
There is only one n and all ptr's are equal.
So, no.

deleting reference to dereferenced int

Even though the following piece of code compiles and runs fine i want to know if it is a valid c++ code?
int main()
{
int *i= new int;
cout<<*i;
int &ref=*i;
cout<<ref;
delete &ref; //Especially is this statement valid?
return 0;
}
If it is valid then this must also be valid :
int& getInt() {
int* i = new int;
return *i; // OK?
}
int main(){
int& myInt = getInt(); // these two lines are same as shown in the example above ?
delete &myInt; //is this OK too?
}
It's correct code and it will work on all platforms and compilers.
However, it's probably not best practice as the reference is usually used when the called party retains the ownership of the object.

C++11 strange behavior with classes, pointers and global scope declarations

[Global Scope]
myClass *objA, *objB, *obj;
int objnum;
I want to switch between objA and objB and assign them alternatively to obj, so in main() I have:
int main()
{
objA = new myClass(parameters...);
objB = new myClass(parameters...);
// start with objA;
objnum = 0;
obj = objA;
}
At some point a function is called that switches between the two objects:
void switchObjects()
{
if (++objnum > 1) objnum = 0;
obj = objnum == 0 ? objA : objB;
}
And in the function where I use the object, I have:
void doYourJob()
{
int res = obj->work();
}
Now the weird thing is that if I don't assign obj to either objA or objB, it still works. I would expect an exception, instead. Even if I do obj = NULL;, it still works! What's this voodoo?
OK, I could provide a different example that brings to the same result, without using a NULL pointer:
myClass *obj[2];
int objnum;
void switchObject()
{
if (++objnum > 1) objnum = 0;
}
void doYourJob()
{
res = obj[objnum]->work();
}
int main()
{
obj[0] = new myClass(parameters...);
obj[1] = new myClass(parameters...);
objnum = 0;
}
With the above code, regardless of the value of objnum, I still get both objects working together, even if I'm calling work() on only one instance.
And if I replace the function doYourJob() with this:
void doYourJob()
{
int res1 = obj[0]->work();
int res2 = obj[1]->work();
}
I always get the results doubled, as if I were calling the function work() twice on every object.
Consider a simpler example:
#include <iostream>
struct X
{
void foo() { std::cout << "Works" << std::endl; }
};
int main() {
X* x = nullptr;
x->foo();
}
With most compilers and on most platforms, this code will appear to work fine, despite having called foo on a null pointer. However, the behaviour is technically undefined. That is, the C++ language gives no restrictions about what might happen if you do this.
Why does it work? Well, calling a member function only requires knowing the type of the object it is being called on. We know that x points at an X, so we know what function to call: X::foo. In many cases, it may be difficult or even impossible to know if a pointer points at a real object, so the compiler just lets it happen. The body of the function, in this case, doesn't actually depend on the X object actually existing, so it just works. This isn't something you can depend on though.

re-initialize a struct's members

It's easy to create and initialize a struct...
struct S{ int x; bool b; };
S s = {123,false};
But is it possible to use the same trick on an existing object? Or is this a 1-time only thing?
S s = {123,false};
s = {456,true}; //fails
s = S(){456,true}; //fails
Is there a syntax trick... obviously I could do:
S s = {123,false};
S temp={456,true};
s = temp;
But can I remove explicitly declaring the temp variable?
I should add I'm working on VC++ 2008, so no fancy modern C++ stuff is available :(
No. Initialization is a one time occurrence. Initialization occurs only when you create as well as assign some values to the created object at the same time (i.e., in one statement0.
Once the object is created you can only assign new values to it.
In short,
You can't reinitialise anything in C++. You can initialise objects or you can assign them.
Once you understand this fact, you can see that there are number of solutions possible such as
passing the structure members to the constructor & creating the structure object of it
overloading the =operator to do whatever you want
You could add a constructor to your struct and then you could do something like:
struct S
{
S(int x_in, bool b_in): x(x_in), b(b_in) { }
int x;
bool b;
}
S s(123, false);
s = S(456, true);
In c++11 you can:
s = S({456, true});
In C++11, an you can construct a temporary from an initializer list and use it with assignment operator. Thus you can write:
struct S {
int x;
bool b;
};
int main()
{
S s = {42, true};
s = {0, false};
}
I dont think struct would support re initialization by default.
S s = {123,false};
S temp={456,true};
s = temp; //calls the = operator
Maybe you could try overloading the assignment operator
Or you can try creating temp on the fly.
S s = {123,false};
s = S (456,true); // this should work i suppose