说我有以下课程:
class A{ };
Run Code Online (Sandbox Code Playgroud)
然后在我的代码中我有一个函数:
A foo(){
A ret;
//Do stuff
return ret;
}
Run Code Online (Sandbox Code Playgroud)
然后我稍后使用该功能....
优化编译器(如g++
)是否只是foo()
像处理void
函数一样处理并跳过实际为空对象分配内存?它可能不会这样做,因为即使空类的大小为1.
假设我有以下课程:
struct A{
void method(A& otherA) const{
/* Mutate otherA */
}
};
Run Code Online (Sandbox Code Playgroud)
然后我有这个:
A myA;
myA.method(myA);
Run Code Online (Sandbox Code Playgroud)
我告诉编译器method
不会更改this
实例,但编译器是否意识到我可以将this
实例作为参数传递?
这样做我可以打破这些东西吗?这是定义的行为吗?
我在实现AVR系列处理器的关键部分方面经验丰富,您所做的只是禁用中断(当然有内存屏障),执行关键操作,然后重新启用中断:
void my_critical_function()
{
cli(); //Disable interrupts
// Mission critical code here
sei(); //Enable interrupts
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:
这种简单的方法是否也适用于处理器的ARM体系结构?我听说过处理器在指令和其他黑魔法上做了先见之事,并且主要想知道这些类型的事情是否会对关键部分的这种实现产生问题.
假设我有以下两个类:
template<typename T>
struct Base
{
void foo();
};
struct Derived : Base<Derived> {};
Run Code Online (Sandbox Code Playgroud)
我可以做这个:
void (Derived::*thing)() = &Derived::foo;
Run Code Online (Sandbox Code Playgroud)
编译器很高兴(正如我所料).
当我把它放在两个级别的模板中时突然爆炸:
template<typename T, T thing>
struct bar {};
template<typename T>
void foo()
{
bar<void (T::*)(),&T::foo>{};
}
int main()
{
foo<Derived>(); // ERROR
foo<Base<Derived>>(); // Works fine
}
Run Code Online (Sandbox Code Playgroud)
这失败了:
non-type template argument of type 'void (Base<Derived>::*)()' cannot be converted to a value of type 'void (Derived::*)()'
Run Code Online (Sandbox Code Playgroud)
为什么简单的案例工作而更复杂的案例失败了?我相信这与这个问题有关,但我并不完全确定......
假设我有一个具有单个抽象虚函数的类,如下所示:
class MyClass{
public:
virtual void MyFunc() = 0;
};
Run Code Online (Sandbox Code Playgroud)
我没有其他功能,也没有数据成员。我还可以保证所有继承自 this 的类都没有任何数据成员,并且除了MyFunc
.
强迫你拥有一个指向抽象对象的指针的最大原因(至少在我看来)是实现的大小是未知的......所以有没有办法而不是让一个指向这个类的指针只给出一个类的实例(或伪实例)。以这个为例:
void AFunction(MyFunc inst){ //Note the lack of pointer
inst.MyFunc(); //This should call the implementation
}
Run Code Online (Sandbox Code Playgroud)
那么这是可能的还是我只是一个一厢情愿的思想家?
假设我有一个名为的代理类List
,它只不过是一堆typename
s 的持有者:
template<typename... items> class List {
constexpr size_t SizeOf = /*Magic code that determines the length*/;
};
Run Code Online (Sandbox Code Playgroud)
假设我有另一个类,它应该接受Lists
并输出一个版本,其中较小的版本用null_t
s 填充:
template<class flist,class slist>
class Pad{
typedef /*Undertermined*/ Flist;
typedef /*Undertermined*/ Slist;
};
Run Code Online (Sandbox Code Playgroud)
唯一真正的问题是破坏递归......通常在模板递归中,您只需专门化,然后就可以结束它。
这里有点不同,因为没有办法(至少我可以看到)通过模板减速来区分两个列表之间的差异。
我尝试使用 astd::conditional
来结束循环,但这不起作用。
这是一个例子:
template<int x>
class Mine{
typedef std::conditional<x == 12, Mine<x>::value, Mine<x+1>::value> value;
};
Run Code Online (Sandbox Code Playgroud)
即使我有条件,x==12
它仍然需要(或想要)清除Mine<x+1>::value
.
那么这个场景的总体策略是什么呢?
假设我在c中有一个基本程序,并且用clang编译它,如下所示:
#include "stdio.h"
int x = 0x7FFFFFFF;
int main(void)
{
printf("%d\n",x);
}
Run Code Online (Sandbox Code Playgroud)
将其编译clang -emit-llvm temp.c -fno-rtti -O3 -S
产生以下位码:
; ModuleID = 'temp.c'
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i686-pc-linux-gnu"
@x = global i32 2147483647, align 4
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%0 = load i32, i32* @x, align 4, !tbaa !1
%call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds …
Run Code Online (Sandbox Code Playgroud) 假设我有这个代码:
#include <iostream>
struct Mine
{
int a;
int b;
};
int main()
{
int Mine::* memberPointerA = &Mine::a;
int Mine::* memberPointerB = &Mine::b;
std::cout << memberPointerA;
std::cout << "\n";
std::cout << memberPointerB;
}
Run Code Online (Sandbox Code Playgroud)
当我使用Microsoft Visual C++(2015)运行它时
我得到以下输出
1
1
Run Code Online (Sandbox Code Playgroud)
我期望的输出更像是这样的:
1
2
Run Code Online (Sandbox Code Playgroud)
所以这引出了一个问题:这个成员指针的打印是否定义了行为?
假设我有一个这样的类:
#include <new>
struct thing {
thing() = default;
void foo()
{
this->~thing();
new (this) thing();
}
};
Run Code Online (Sandbox Code Playgroud)
是这样调用析构函数然后使用放置新定义的行为重建对象?
假设我有一段像这样的代码(并假设填充是按照我在评论中所说的插入的):
#include "stdint.h"
struct A
{
uint8_t x;
// 3 bytes of padding
uint32_t y;
};
void foo(struct A* a)
{
a->x = 0;
}
Run Code Online (Sandbox Code Playgroud)
是否允许编译器清除填充字节或对函数 foo 中的填充字节执行任何操作?
https://en.cppreference.com/w/c/language/object在这个问题上保持沉默,这让我相信编译器可以这样做......
我想知道编译器是否允许这样做的原因是我想要memcmp
两个结构,并且我想知道我可以假设什么......
c++ ×8
c ×3
templates ×2
alignment ×1
arm ×1
bare-metal ×1
clang ×1
const ×1
cout ×1
destructor ×1
inheritance ×1
llvm ×1
new-operator ×1
optimization ×1
padding ×1
pointers ×1
recursion ×1