我正在使用 GCC 为 ARM 开发 C++。我遇到了一个问题,我没有启用优化,我无法为我的代码创建二进制文件(ELF),因为它不适合可用空间。但是,如果我只是启用调试优化(-Og)(据我所知这是可用的最低优化),代码就很容易适应。
在这两种情况下,都会启用-ffunction-sections、-fdata-sections、-fno-exceptions和-Wl,--gc-sections 。
即使进行了最小的优化,二进制大小也存在巨大差异。
我查看了3.11 控制优化的选项,详细了解使用 -Og 标志执行哪些优化,看看这是否会给我任何见解。
哪些优化标志对二进制大小影响最大?我应该寻找什么来解释这种巨大的差异吗?
我最近遇到了“特质”这个有趣且强大的概念,并尝试在 C++ 中理解/实现它们。据我了解,特征提供了一种方法,既可以扩展/调整现有代码的功能,又可以为类定义“接口”,而无需使用传统继承(以及随之而来的所有开销/问题)。我还看到这个概念似乎与C++中的CRTP设计模式密切相关。
举个例子,我用 C++ 编写接口的正常思维过程是定义一个具有纯虚方法的类。然后我可以创建它的子类并将指针传递给我的所有通用代码。然而我发现这有一些问题:
下面是一个简单、传统的 Light 界面示例:
class Light {
public:
virtual void on() = 0;
virtual void off() = 0;
};
class MyLight : public Light {
public:
void on() override;
void off() override;
};
void lightController(Light& l) {
l.on();
l.off();
}
Run Code Online (Sandbox Code Playgroud)
并且(基于此处的文章: https: //chrisbranch.co.uk/2015/02/make-your-c-interfaces-trait-forward/)这是我认为的“基于特征”的实现相同的概念:
template<typename T>
class Light {
public:
Light(T& self) : _self(self) {}
void on() { _self.on(); }
void off() { _self.off(); }
private:
T& _self;
};
class …
Run Code Online (Sandbox Code Playgroud) 我试图弄清楚如何使用“更专业”的可变参数函数模板“重载”可变参数函数模板。例如:
#include <iostream>
template <typename... ARGS_>
void foo(void(*fn)(ARGS_...)) {
std::cout << "Generic function pointer foo" << std::endl;
}
struct Test {
};
template <typename... ARGS_>
void foo(void(*fn)(ARGS_..., Test*)) {
std::cout << "Test function pointer foo" << std::endl;
}
void test1(int a, int b) {
std::cout << "test1()" << std::endl;
}
void test2(int a, int b, Test* x) {
std::cout << "test2()" << std::endl;
}
int main() {
foo(&test1);
foo(&test2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这段代码的输出是:
Generic function pointer foo
Generic function pointer …
Run Code Online (Sandbox Code Playgroud) 假设我有以下课程
class Example {
public:
using value_type = std::tuple<
uint8_t,
uint8_t,
uint16_t
>;
private:
value_type _value;
};
Run Code Online (Sandbox Code Playgroud)
现在,我希望能够基于此类型创建另一个类,将每个类类型包装在另一种类型中。基于将每种类型包装在模板化类中的可变参数模板中,我知道我可以通过以下方式实现一半的目标:
template <typename T>
class Wrapper;
template <typename ... ARGS>
class ExampleWrapper {
private:
std::tuple<Wrapper<ARGS>...> _args;
};
Run Code Online (Sandbox Code Playgroud)
但是,我无法弄清楚的是,ARGS
如果我所知道的就是ExampleT
在哪里,如何获取T
Example。我希望能够使用ExampleWrapper
如下:
ExampleWrapper<Example> myWrapper;
Run Code Online (Sandbox Code Playgroud) 在 C++17 中,是否有办法在编译时生成前 N 位设置的常量?
在伪代码中,我正在寻找类似的东西:
constexpr uint32_t MY_CONSTANT = setBits<2>();
Run Code Online (Sandbox Code Playgroud)
相当于:
constexpr uint32_t MY_CONSTANT = 0b11;
Run Code Online (Sandbox Code Playgroud)
换句话说,给定编译时常量 N,返回编译时常量 M,其中位 0 到 (N-1) 为 1(设置)。
我试图弄清楚如何根据模板的结果来特殊模板类。例如,假设我有以下基本模板类:
enum class BasicType
{
UNKNOWN,
PRIMITIVE,
OBJECT
};
template <typename T>
struct traits
{
static constexpr BasicType type = BasicType::UNKNOWN;
};
Run Code Online (Sandbox Code Playgroud)
我希望能够创建特征的专门化,例如,对于 std::is_integral_v 为 true 的任何类型。然后是另一个专业,其中另一个特征是正确的。
我尝试过这样的事情
template <typename T>
struct traits<std::enable_if_t<std::is_integral_v<T>, T>>
{
static constexpr BasicType type = BasicType::PRIMITIVE;
};
Run Code Online (Sandbox Code Playgroud)
但这行不通。
我正在尝试编写一些代码,通过将函数调用及其参数存储在 lambda/std::function 中,允许我稍后调用函数。理想情况下,参数只会被复制一次(并以其他方式移动),但我可以实现的最小副本数似乎是 2。
//==============================================================================
// INCLUDES
//==============================================================================
#include <iostream>
#include <functional>
#include <memory>
//==============================================================================
// VARIABLES
//==============================================================================
static std::unique_ptr<std::function<void()>> queueFunction;
//==============================================================================
// CLASSES
//==============================================================================
class Test {
public:
Test(int a, int b = 20, int c = 30) : _a(a), _b(b), _c(c) {
std::cout << "Test: Constructor" << std::endl;
}
~Test() {
std::cout << "Test: Destructor" << std::endl;
}
Test(const Test& other) :
_a(other._a)
{
std::cout << "Test: Copy Constructor" << std::endl;
}
Test(Test&& other) :
_a(std::move(other._a))
{
std::cout …
Run Code Online (Sandbox Code Playgroud) 我知道在 C/C++ 中,如果您编写一个字符串文字,它实际上会被放入具有静态(程序生命周期)存储的只读内存中。因此,例如:
void foo(const char* string) {
std::cout << static_cast<void const*>(string) << std::endl;
}
int main() {
foo("Hello World");
}
Run Code Online (Sandbox Code Playgroud)
应该打印出指向只读内存中某个位置的指针。
这是我的问题,假设我想编写一个写时复制 String
类,它对这样的静态数据进行优化。与其将整个字符串复制到动态分配的内存中(这很昂贵),为什么不只保留指向静态数据的指针呢?然后,如果确实需要进行写入,那么我可以在此时制作一个副本。
但是我如何判断字符串是静态的还是类似的:
int main() {
char[] myString = "Hello World";
foo(myString);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,myString 位于堆栈中而不是堆中,因此它的生命周期不是静态的。
我的第一个想法是 的特殊构造函数std::string_view
,但我不确定这std::string_view
是否意味着具有静态生命周期的字符串......
假设我有以下非常简单的类:
class A
{
public:
static constexpr A make() { return A{}; }
constexpr A() : _v(0) {}
constexpr A& setV(int v) { _v = v; return *this; }
private:
int _v;
};
Run Code Online (Sandbox Code Playgroud)
如果我尝试按如下方式使用它:
int main()
{
volatile A a1;
a1.setV(10);
//OR
//The optimizer will optimize this chain of constexpr calls into a single "store" instruction
a1 = A::make().setV(10); //More chaining here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该代码将无法编译。
我理解为什么这是真的,基于:定义易失性类对象
我知道解决方案是添加一个额外的方法,如下所示:
class A
{
public:
constexpr A() : _v(0) {}
volatile A& …
Run Code Online (Sandbox Code Playgroud) 我经常编写具有类似于以下签名的工厂:
std::unique_ptr<AbstractType> createUnique(IDType id);
std::shared_ptr<AbstractType> createShared(IDType id);
Run Code Online (Sandbox Code Playgroud)
前者会做类似的事情:
switch (id)
{
case kID1:
return std::make_unique<Type1>();
}
Run Code Online (Sandbox Code Playgroud)
而后者
switch (id)
{
case kID1:
return std::make_shared<Type1>();
}
Run Code Online (Sandbox Code Playgroud)
那么,这两个函数之间的唯一区别是使用的“make”函数(make_shared
或make_unique
)和返回类型(shared_ptr
或unique_ptr
)。这会导致代码重复。
我想知道如何编写一个create
接受指针类型和“make”函数类型并使用它们的模板化函数。就像是:
template <typename PTR, typename MAKE>
PTR create(IDType id)
{
switch (id)
{
case kID1:
return MAKE<Type1>();
}
}
Run Code Online (Sandbox Code Playgroud)
我知道以上不是有效的代码。
另外,我知道 astd::shared_ptr
可以从 an 创建,std::unique_ptr
反之亦然,但我这个工厂将用于不同的应用程序,其中一个可能使用 a shared_ptr
,另一个可能使用unique_ptr
. 这样,代码就可以重复使用,而且对于特定的用例也很有效。