Skip to content

Instantly share code, notes, and snippets.

@linuskmr
Last active September 9, 2022 18:32
Show Gist options
  • Save linuskmr/490dbed2d3d9db1d37b900c7992c052c to your computer and use it in GitHub Desktop.
Save linuskmr/490dbed2d3d9db1d37b900c7992c052c to your computer and use it in GitHub Desktop.
Funny/Strange C++ Code Examples
#include <iostream>
#include <string>
// Assume we have a class 'MyClass` and the following code:
//
// 1. MyClass a;
// 2. MyClass b = a;
// 3. b = a;
//
// Does statement 3 have any effect, or could we delete it
// and the code would to the same as before?
// Surprisingly, statement 3 matters!
//
// This is because in statement 2, the 'copy constructor' is called,
// but in statement 3, the 'assignment operator' is called.
class MyClass {
public:
// Stores the last action (creation, copy or assignmemt)
std::string message = "last operation was creation";
int* v;
MyClass() = default;
// Copy constructor
MyClass(MyClass & other) {
int count = new int(3);
message = "last operation was copy";
}
// Assignment operator
MyClass& operator=(MyClass other) {
message = "last operation was assignment";
return *this;
}
};
int main() {
MyClass a;
std::cout << a.message << std::endl;
// "last operation was creation"
MyClass b = a;
std::cout << b.message << std::endl;
// "last operation was copy"
b = a;
std::cout << b.message << std::endl;
// "last operation was assignment"
}
#include <iostream>
class AssignmentCounter {
public:
int count = 0;
AssignmentCounter& operator=(AssignmentCounter other) {
count++;
return *this;
}
bool operator<(int other) {
return count < other;
}
};
int main() {
AssignmentCounter counter;
while (counter.count < 10) {
std::cout << counter.count << std::endl;
// ⬇️
counter = counter;
}
std::cout << "---" << std::endl;
for (AssignmentCounter counter; counter < 10; counter = counter) {
std::cout << counter.count << std::endl;
}
}
#include <vector>
using namespace std;
class IntWrapper {
public:
int x;
IntWrapper(int xInit) : x(xInit) {}
};
int main() {
vector<IntWrapper> intWrapperVec;
// Does this produce a compile error?
intWrapperVec.emplace_back(42);
// No, it doesn't! The constructor of IntWrapper is not marked `explicit`, so the number is automatically
// converted to an IntWrapper instance.
}
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
class ThreadExample {
public:
int x = 0;
ThreadExample() {
// Here we create a thread in which the member function printHelloWorld() is called. Here the value of x == 0.
thread t([this]() {
setXto42();
});
t.join();
// The question is: What is the value of x here? Did the thread t work on a copy of ThreadExample? Then x
// would still be 0, because setXto42() only changed the copy. But in fact `this` is a pointer. `this` is
// captured in the lambda as a *copy*, but not the actual memory where ThreadExample is stored. So the
// thread changes the original. Therefore x is 42 here.
}
void setXto42() {
x = 42;
}
};
int main() {
ThreadExample threadExample;
}
#include <iostream>
#include <vector>
#include <thread>
#include <unistd.h>
using namespace std;
void printHelloWorld() {
cout << "Hello World!" << endl;
}
int main() {
// What happens here? Does this create a thread that executes printHelloWorld?
thread(printHelloWorld);
sleep(3);
// No! Note the compiler's warning saying that the outer parentheses around (printHelloWorld) are
// unnecessary. Ok, that means you can omit them. Let's do that:
// thread printHelloWorld;
// Oops. We have created a thread here called printHelloWorld that does nothing.
// What do we learn from this? Always give your threads a name.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment