|
|
I feel I'm turning slightly mad. In my mind the two variants below should give the same output:
class A {
public:
A () { cout << "A created" << endl; }
};
class B {
public:
B () { cout << "Default B constructor" << endl; }
B (A oa) { cout << "B created from A" << endl; }
B (const B& other) { cout << "B copy constructor" << endl; }
};
int main()
{
A aobj;
B* bptr = new B (B (aobj));
cout << "--------" << endl;
B bobj (aobj);
B* bbptr = new B (bobj);
}
After A is created, I create a B from A and then I copy the B using the copy constructor. At least that's my intention.
However the output I get is:
A created
B created from A
--------
B created from A
B copy constructor
What am I missing here?
Mircea
|
|
|
|
|
I might be wrong, but
B (aobj) from
new B (B (aobj)) should call move constructor, not copy constructor ...
P.S.
B (B (aobj)) would call a copy constructor only if what is inside of first brackets would be an already created B object, a l value, so, since
B (aobj) is an anonymous object, move construct would be called.
P.P.S. I added move constructor to B
B(B&& rhs) { std::cout << "B move constructor" << std::endl; }
and is never called either.
modified 23-Sep-20 6:34am.
|
|
|
|
|
The standard says that a move constructor is generated by default only for classes that don'
t have a copy constructor. Otherwise the copy constructor is invoked. It has to be like that for compatibility reasons: move constructors were introduced only in C++11.
As you did, I've also tried adding the move constructor with the same results
Mircea
|
|
|
|
|
I stepped through that code with the debugger, and it appears that it treats new B (B (aobj)); the same as new B (aobj); . That is to say, it optimises out the creation of the interim object, as it is never needed.
|
|
|
|
|
I was also ready to blame the compiler except that I was using the code in debug mode with all optimizations turned off. You can try it even with something like i=1;i=2; and you will see that it is generating not optimized code.
Besides, my code is abstracted from a real world program where the copy constructor was making a deep copy of an object full of pointers and memory allocations. I cannot see the compiler simply throwing away all those side-effects.
Also I tried with both VisualStudio and g++ and both compilers behave the same way. It must be something deeper in this than a compiler bug.
As I use to say in these cases: the silly is on the other side of the screen
Mircea
|
|
|
|
|
A more thorough use of Google brought me the this:
Quote: Whenever a temporary object is created for the sole purpose of being copied and subsequently destroyed, the compiler is allowed to remove the temporary object entirely and construct the result directly in the recipient (i.e. directly in the object that is supposed to receive the copy).
This process is called elision of copy operation. It is described in [class.copy.elison] in the language standard.
In this case
B* bptr = new B(B(aobj));
can be transformed into
B* bptr = new B(aboj);
even if the copy constructor has side-effects.
Mircea
|
|
|
|
|
|
I'm somewhat impressed by this compiler, but the compiler is allowed to means that it could behave differently under different compilers, especially if the construction of the temporary object has side effects.
|
|
|
|
|
On the contrary: I'm quite unimpressed ("we are not amused").
You know what they say that C makes it easy to shoot yourself in the foot and C++ gives you a bazooka. In this case I's say you walk with hand grenades in your pocket; safety pins are optional.
Note that even in the variant that 'works':
B bobj (aobj);
B* bbptr = new B (bobj);
bobj is susceptible to being optimized out of existence and turned back into the previous case.
To leave it to the compiler, or the compiler designer, if a function should be called or not, and to do it without even a warning, is unconscionable. Haven't researched the history of this section of the standard but I'd dare say that it dates back to the '03 time and the 'efficiency wars'. That was put to rest with the '11 move constructors and assignment operators but probably that section of the standard slipped through.
In fairness, I should say that it's not something that happens too often. This is the first time I run into the issue but I'll keep it in mind for the future.
Mircea
|
|
|
|
|
Yes. I'm very unimpressed by the spec but still impressed that the compiler bothered to implement this "optimization".
|
|
|
|
|
What compilers (and linkers) do you use to compile pure assembler code/files? On Microsoft website MASM has Visual Studio 2005 as prerequisite.
|
|
|
|
|
|
You may want to check out NASM[^]
|
|
|
|
|
What`s sets them apart from each other? Will they produce binary for everything that runs on AMD/Intel processors (taken that you link to the appropriate libraries)? Are there standards that ASM code needs to meet to run on any specific OS?
|
|
|
|
|
I am writing code for an ARM processor and compiling with GCC inside Eclipse IDE. My project has 3 files, main.c, myDummyFile.h and myDummyFile.cpp. myDummyFile.h:
#ifndef MYDUMMYFILE_H_
#define MYDUMMYFILE_H_
#ifdef __cplusplus
extern "C" {
#endif
int myDummyFunction();
#ifdef __cplusplus
} #endif
#endif /* MYDUMMYFILE_H_ */ myDummyFile.cpp:
#include <functional>
using namespace std;
using cPlusPlusCallback_t = function <int(int myParam)>;
volatile int preventOptimizationDummy = 0;
int myDummyFunction() {
return preventOptimizationDummy++;
} main.c:
#include <stdio.h>
#include <stdlib.h>
#include "myDummyFile.h"
int main(int argc, char* argv[]) {
return myDummyFunction();
} Does anybody know why I get the error message "undefined reference to `myDummyFunction'" when I try to compile this? If I remove the call to myDummyFunction() then it compiles fine so the compiler does seem to be able to compile .cpp-files.
|
|
|
|
|
You need to add the following line to myDummyFile.cpp:
#include "myDummyFile.h"
Otherwise the compiler will generate a decorated* name for myDummyFunction , because the source file is C++ not C.
*In C++ external names have additional characters so the linker will not match what is called from your main file.
|
|
|
|
|
I know that SHGetFileInfo will get me the icon that is displayed for a known file type (by the file extension,) but how do I get the icon that the shell displays for an executable file? In other words, I don't want an icon from the system image list, I want the one for the executable file.
Any pointers are much appreciated.
SOLUTION: I found the ExtractIconEx function, which does what I need.
The difficult we do right away...
...the impossible takes slightly longer.
modified 9-Sep-20 21:32pm.
|
|
|
|
|
I am writing code for an ARM processor and compiling with GCC. I have done some C# programming and there you're allowed to pass anonymous arrays and structs directly in method calls:
MyClass.MyMethod1(new byte[]{0, 1, 2, 3}); and
MyClass.MyMethod2(new MyStruct("", 0, null)); What's the closest thing I can achieve the same thing in my ARM-project?
myFunction1({0, 1, 2, 3}); myFunction2({"", 0, NULL}); I understand that I could change my function to take a function pointer instead of a struct as a parameter using the technique described in Re: What's the closest thing to anonymous function pointers I can achieve that compiles with GCC? - C / C++ / MFC Discussion Boards[^]:
#include <functional>
using namespace std;
using getMyStructCallback_t = function <struct MyStruct*()>;
void myFunction(getMyStructCallback_t getMyStructCallback);
myFunction([]() {
static struct MyStruct myStruct = {"", 0, NULL}; return &myStruct;} ); but if possible, then I would like to pass my struct/array directly.
|
|
|
|
|
Check this:
struct MyStruct
{
const char* s;
int i;
void* ptr;
};
class MyClass
{
public:
MyClass ();
void MyMehod1 (const std::vector<int>& v) {};
void MyMethod2 (const MyStruct& s) {};
};
int main()
{
MyClass c;
c.MyMehod1 ({ 0, 1, 2, 3 });
c.MyMethod2 ({ "", 0, nullptr });
}
Mircea
|
|
|
|
|
Is it possible to do without classes/object orientedness?
|
|
|
|
|
Your question had this code:
MyClass.MyMethod1(new byte[]{0, 1, 2, 3});
Here you a calling a method (also called member function) of an object. So your code is already object oriented.
Maybe you should revise/clarify what you want to accomplish.
Mircea
|
|
|
|
|
That was a C# example, to indicate that I was looking for the corresponding C/C++ syntax for my ARM-project. I try to keep my ARM-code as close to pure C-programming as possible (this will obviously be an exception) and never use classes in the ARM-project. Is anything in your example dependent on the classes or will it compile just fine without classes? I'm not at work so I can't try it for myself right now, but I plan to work on this first thing in the morning.
|
|
|
|
|
arnold_w wrote: I try to keep my ARM-code as close to pure C
arnold_w wrote: I plan to work on this first thing in the morning. When you get back into the office please print out __STDC_VERSION__ so we know which language version you are working under. The C99 language and below had no support for anonymous structures or unions. But the GCC compiler has a non-standard extension -std=gnu99 that enables it.
Support for anonymous structures or unions was added in C11[^] back in 2011
If your __STDC_VERSION__ is 199901L or above then you should be able to use anonymous objects.
Best Wishes,
-David Delaune
|
|
|
|
|
You could do something like:
void Function(const std::vector<uint8_t>& values) Call it as follows:
Function(std::vector<uint8_t>{ 5, 4, 3}); (Works with VC++ 2017. Should work with GCC.)
|
|
|
|