小编Daw*_*dPi的帖子

函数指针的解释

我有一个问题,理解一些C++语法结合函数指针和函数声明,即:

通常当我们想要声明一种类型的函数时,我们会做如下:

typedef void(*functionPtr)(int);
Run Code Online (Sandbox Code Playgroud)

这对我来说没问题.从现在开始,functionPtr是一个类型,它表示指向函数的指针,它返回void并以值作为参数获取int.

我们可以使用它如下:

typedef void(*functionPtr)(int);

void function(int a){
    std::cout << a << std::endl;
}

int main() {

    functionPtr fun = function;
    fun(5);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我们5打印在屏幕上.

我们有指向函数的指针fun,我们为函数分配了一些现有的指针 - function我们通过指针执行这个函数.凉.

现在正如我在一些书中读到的那样,函数和指向函数的方法在某种程度上是相同的,所以事实上在function()每次声明函数声明函数后我们指的是真正的函数和指向同一类型函数的指针,所以下面的编译和每个指令给出相同的结果(5在屏幕上打印):

int main() {

    functionPtr fun = function;
    fun(5);
    (*fun)(5);
    (*function)(5);
    function(5);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以现在只要我能想象,那些指向函数和函数的指针几乎是一样的,那么它对我来说就好了.

然后我,如果指向函数和实函数的指针是相同的,那么为什么我不能做以下事情:

typedef void(functionPtr)(int); //removed *

void function(int a){
    std::cout << a << std::endl;
}

int main() {

    functionPtr fun = function;
    fun(5);

    return 0;
} …
Run Code Online (Sandbox Code Playgroud)

c++ pointers typedef function

20
推荐指数
1
解决办法
2824
查看次数

此枚举声明是否符合标准?

因此,通常枚举用于将"常量整数"组声明为另一种类型,代表某种东西.例如.

enum Color {RED=0, BLUE, YELLOW};
Run Code Online (Sandbox Code Playgroud)

这很清楚.但最近我在代码中遇到了以下内容.这是嵌入式系统的编译器.

enum State {DISABLED=0, ENABLED=!DISABLED};
Run Code Online (Sandbox Code Playgroud)

它运作得很好.它表现为布尔类型.我的问题是,它(这种语法)是否符合ANSI标准?

如果它符合标准,那么为什么编译器会在内部定义像_Bool这样的布尔表示,然后在stdbool.h(对于C语言)它们:

#define bool _Bool
... // here goes definitions of true and false
Run Code Online (Sandbox Code Playgroud)

代替

enum bool {false=0, true=!false};
Run Code Online (Sandbox Code Playgroud)

哪个更干净?

c c++ enums

11
推荐指数
2
解决办法
462
查看次数

为什么C++ 17向命名空间和枚举器添加属性?

正如问题所述,我知道在C++ 17中会有名称空间和枚举器的属性.这将如何影响我们的代码?这些属性是什么以及它们允许我们做什么?我找不到任何理解这个新功能的好资源.

c++ standards enums namespaces

10
推荐指数
1
解决办法
1482
查看次数

C++外部类访问内部类的私有 - 为什么禁止

您好我想知道为什么C++标准允许我们在嵌套类中访问外部类的私有字段,而它禁止从外部类访问内部类的私有字段.我明白了,这个例子:

class OuterClass{
public:
    class InnerClass{
    public:
        void printOuterClass(OuterClass& outer) {cout << outer.m_dataToDisplay;};
    };
private:
    int m_dataToDisplay;
};
Run Code Online (Sandbox Code Playgroud)

很好,因为内心,有时可能会很复杂.但我认为以下情况也很好:

class Algorithm{
public:
    class AlgorithmResults{
    public:
        void readAlgorithmResult();
    private:
        void writeAlgorithmResult();
    };

    void calculate(AlgorithmResults& results, Arguments...){
       //calculate stuff
       results.writeAlgorithmResult(results);
    }
};
Run Code Online (Sandbox Code Playgroud)

对我来说,这种结构非常有意义,尽管在C++中是不允许的.我也注意到,有一段时间两者都被Java所允许,但现在第二个例子也被禁止了.是什么原因,第一个例子被允许而另一个被拒绝?

c++ private

10
推荐指数
3
解决办法
7662
查看次数

非const引用指向const对象的非const指针

简单来说,我有一个简单的指针:

int* a;
Run Code Online (Sandbox Code Playgroud)

现在,我想改变这个指针的值.我想在一个函数中这样做.函数确保它不会改变指针指向的对象,但会改变指针本身.这就是为什么我希望这个函数接受如下参数:非const引用(因为指针的值将被改变)到指向const对象的非const指针(指针本身可以改变)(函数保证,该对象,指针指向不会被改变).

最简单的功能是:

void function(const int*& a){
    a = 0;
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试调用此函数时:

int main(){
    int* a;
    function(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器不满意并说:

从'const int*'函数(a)的rvalue初始化'const int*&'类型的非const引用;

我不太明白这个错误,因为对我来说没有涉及rvalue(我传递对象的引用,已经存在于堆栈中.)

问题是,我该怎么做呢?

可以在此处找到示例:https://ideone.com/D45Cid


编辑:

有人建议,我的问题是为什么将"指向非const的指针"转换为"指向const的指针"是不合法的.

我的问题是不同的,因为我没有使用指针指针我只使用指向对象/值的指针并存储对它的引用,因此情况就像在回答这个问题:

const char c = 'c';
char* pc;
const char** pcc = &pc;   // not allowed
*pcc = &c;
*pc = 'C';                // would allow to modify a const object
Run Code Online (Sandbox Code Playgroud)

在我的情况下是不可能的,因为我无法取消引用顶级指针(我没有这样的指针).

此外,我质疑这个问题的完美和干净的解决方案,这个问题没有涉及

c++ pointers reference

10
推荐指数
1
解决办法
1671
查看次数

auto和static_casts - 良好的做​​法

在Scott Meyer的书"Effective Modern C++"中,我们可以读到:

std::vector<bool> features(const Widget& w);
Widget w;
…
bool highPriority = features(w)[5];
…
processWidget(w, highPriority); 
Run Code Online (Sandbox Code Playgroud)

以及auto的选项

auto highPriority = features(w)[5];
Run Code Online (Sandbox Code Playgroud)

这会导致未定义的行为,因为features()返回的事实是std::vector<bool>,std::vector<bool>::reference在返回值时使用类型的代理对象opearator[].

作为解决方案,建议不要停止使用auto,而是使用static_casts.

所以Scott Meyers建议使用:

auto highPriority = static_cast<bool>(features(w)[5]);
Run Code Online (Sandbox Code Playgroud)

代替:

bool highPriority = features(w)[5];
Run Code Online (Sandbox Code Playgroud)

我的问题是:这两者之间有什么真正的区别?在我看来两者都是相同的,因为这两种方法都以完全相同的方式使重构变得更难(在函数功能中改变返回值类型不会使变量highPriority成为不同类型)而第二种方法更短.

c++ coding-style c++11

7
推荐指数
2
解决办法
1601
查看次数

责任链与有限状态机 - 差异

因此,我是一名电工和程序员,我认为我非常了解FSM设计模式.它是:

  • 我们有一套Nodes,
  • Node当程序在此节点中时,每个人都知道该做什么,
  • 每个人都Node contains references to another chosen nodes知道在什么条件下,他应该继续选择一个.
  • eventafter processing节点,Node proceeds到下一个选择的节点

我想,这对我来说很清楚.虽然最近,当我实施一台国家机器时,一个人告诉我,事实上它有点修改了责任链(不确定他是否正确),而且我做了/做了什么:

  • 一组Nodes(未表示线性或树形结构)
  • 节点有对象,知道在哪种情况下它们应该跳转到哪个节点
  • 每个节点都有自己的处理上下文(节点的某些部分在节点之间共享).

不幸的是,我担心,由于法律问题,我不允许在这里粘贴类图.


另一方面,我们有责任链,我(按照我的理解)以下列方式定义,即:

  • 我们有一些ItemToProcess接口,
  • 我们有一些Node接口,
  • Node 引用一个下一个Node,
  • 每个节点处理ItemToProcess并转发处理过的一个节点nextNode

据我所知:

  • 我们使用Chain Of Responsibility,我们想要一个被处理的项目(或至少试图要处理)的每个节点
  • 责任链表示流程的顺序和持续执行
  • 我们StateMachine用来表示图表
  • 我们StateMachine用来执行计算,计算的顺序或种类可能因某些事件异.

我想请你确认我对这些设计模式的理解,或者告诉我在理解上的错误.

design-patterns state-machine chain-of-responsibility

7
推荐指数
2
解决办法
1966
查看次数

可变参数模板 - 如何创建存储传递参数的类型

所以假设我有一个包含函数对象的类,并且在构造函数调用中我传递参数,这些参数将在稍后传递给函数对象.就像是:

class Binder{
public:
    Binder(functional_object, listOfParameters);
    callFunctionalObject(); // calls functional object with given list of parameters
};
Run Code Online (Sandbox Code Playgroud)

在C++ 11之前,我无法使用Variadic模板,因此可以这样做:

struct none{};

template <typename T1, typename T2=none, typename T3=none>
class Binder{
public:
    Binder(T1 functionalObject, T2 arg1=none(), T3arg3=none());
    void callFunctionalObject();
private:
    T1 m_functionalObject;
    T2 m_arg1;
    T3 m_arg2;
};
Run Code Online (Sandbox Code Playgroud)

哪里callFunctionalobject可以实施如下:

template<typename T1, typename T2, typename T3>
void Binder<T1,T2,T3>::callFunctionalObject(){
    callImpl(m_functionalObject, m_arg1, m_arg2);
}
Run Code Online (Sandbox Code Playgroud)

并且callImpl会重载以识别类型的对象none以将适当数量的参数传递给功能对象.

现在切换到C++ 11我不知道如何实现这个事实,在私有部分我有成员,我可以直接访问.

任何人都可以解释我使用C++ 11或C++ 14的方式吗?

c++ templates variadic-templates c++11

5
推荐指数
1
解决办法
352
查看次数

rvalue保证什么样的优化?

我想用另一个使用rvalue构造一个对象.

class BigDataClass{
public:
    BigDataClass(); //some default BigData
    BigDataClass(BigDataClass&& anotherBigData);
private:
    BigDataClass(BigDataClass& anotherBigData);

    BigDataPtr m_data;
};
Run Code Online (Sandbox Code Playgroud)

所以现在我想做一些事情:

BigDataClass someData;
BigDataClass anotherData(std::move(someData));
Run Code Online (Sandbox Code Playgroud)

所以现在anotherData获得了rValue.事实上,这是一个eXpiring Value,因此http://en.cppreference.com/w/cpp/utility/move状态编译器现在有机会通过将someData移动到另一个来优化anotherData的初始化.

在我看来,我们实际上可以得到两件不同的东西:

  1. 优化方法:数据移动.它经过优化,快速,我们很高兴
  2. 非优化方法:数据未移动.我们必须将数据从对象复制到另一个并从第一个数据中删除数据(据我所知,一旦我们无法使用它,将对象更改为rvalue,因为它没有数据的所有权,它持有).事实上,由于删除操作,它可能比使用左值参考的初始化更慢.

我们真的可以获得如此未经优化的数据初始化方式吗?

c++ optimization rvalue c++11

3
推荐指数
2
解决办法
237
查看次数

C++模板构造函数的默认参数

以一种非常简单的方式.我们有以下代码:

struct templateTest{
    struct {}m_none;
    template <typename T1, typename T2, typename T3, typename T4>
    templateTest(T1 arg1, T2 arg2=m_none, T3 arg3=m_none, T4 arg4=m_none){

    }
};

struct nonTemplate{
    nonTemplate(int arg1, int arg2=2, int arg3=3){}
};

int main()
{
    nonTemplate(5);
    nonTemplate(5,10);

    templateTest test2(5,10);
    templateTest test1(5);


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想要的是模板类中的默认构造函数参数.

默认参数与nonTemplate类完全匹配,但它与templateTest类型不同.我遇到的错误如下:

C2660:'templateTest :: templateTest':函数不带2个参数

用2个参数调用的构造函数

对于使用一个参数调用的构造函数,编译器想要调用copyConstructor,输出如下:

C2664:'templateTest :: templateTest(const templateTest&)':无法将参数1从'int'转换为'const templateTest&'

有没有办法在旧的C++编译器上实现我想要的东西,比如msvc 2011?

c++ templates default-value

3
推荐指数
1
解决办法
966
查看次数

GCC-如何告诉链接器不要跳过未使用的部分

我的问题如下:

我正在尝试编写嵌入式应用程序,该应用程序必须提供它自己的链接程序脚本(使用arm-none-eabi-gcc编译器/链接器)。

嵌入式Bootloader加载二进制文件并从0x8000地址开始,这就是为什么我需要专用的链接描述文件的原因,该脚本允许我将所需的启动函数放入该地址。脚本代码如下:

MEMORY
{
    ram : ORIGIN = 0x8000, LENGTH = 0x1000
}

SECTIONS
{
    .start : { *(.start) } > ram
    .text : { *(.text*) } > ram
    .bss : { *(.bss*) } > ram
}
Run Code Online (Sandbox Code Playgroud)

现在,我要做的就是拥有一个函数,该函数将插入.start部分,因此它位于0x8000的开头。为此,我在库中使用以下功能:

__attribute__((section(".start"))) void notmain() {
    main();
}
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常,但是后来我将此库与带有函数notmain的项目链接,该项目定义了main()函数。在链接过程中,我看不到该.start部分不再存在,并且notmain符号完全丢失。当我将非主要功能移出库(移入项目)后,一切都很好。

我的理解是,链接器看到了,我的应用程序中根本没有使用.start节,这使它跳过了所有节。我已经尝试过为功能notmain添加一些属性,例如(__attribute__((used)) __attribute__((externally_visible))),但是它也没有起作用(最终的二进制文件中notmain仍然缺少)。

CMake的源代码如下:

**专案**

project(AutomaticsControlExample)

enable_language(ASM)

set(CMAKE_CXX_STANDARD 14)

set(SOURCES main.cpp PID.hpp)
set(DEPENDENCIES RPIRuntime PiOS)

add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${DEPENDENCIES})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_OBJDUMP} -D …
Run Code Online (Sandbox Code Playgroud)

linker gcc cmake

2
推荐指数
1
解决办法
856
查看次数

C++ 将 bool 转换为 int - 标准

我感兴趣的是,标准是否会bool在将类型转换为integer类型后对类型类型的可能值进行说明。

例如下面的代码:

#include <iostream>
using namespace std;

int main() {
    bool someValue=false;
    *((int*)(&someValue)) = 50;

    cout << someValue << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印 1,即使它被迫存储值 50。标准是否指定了任何相关内容?或者编译器是否为 bool 类型生成某种方法,如下所示:

operator int(){
    return myValue !=0 ? 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)

另外为什么铸造如下:

reinterpret_cast<int>(someValue) = 50;
Run Code Online (Sandbox Code Playgroud)

因错误而被禁止

错误:从类型“bool”到类型“int”的转换无效

(对于以上所有内容,我使用 GCC 5.1 编译器。)

c++ casting boolean

1
推荐指数
1
解决办法
7087
查看次数

为什么std :: move使用std :: remove_reference?

根据http://en.cppreference.com/w/cpp/utility/move

std::move 声明如下:

template <typename T>
std::remove_reference<T>::type&& move(T&& t);
Run Code Online (Sandbox Code Playgroud)

至于我的理解去,当代码为模板,在扣除Ttypename T失去约的参考信息,所以以下内容:

template <typename T>
void someFunction(T&& value);
Run Code Online (Sandbox Code Playgroud)

使用时如:

int five=5;
someFunction(five);
Run Code Online (Sandbox Code Playgroud)

然后

  • value 是类型的 int&
  • Tint

要么

const float value = 5.25;
someFunction(value);
Run Code Online (Sandbox Code Playgroud)

然后

  • value 是类型的 const float&
  • Tconst float.

如果是这样,那么移动声明中没有必要将返回的类型声明为: std::remove_reference<T>::type&&,因为T已经不是引用了.

此外,如果std::move采用作为参数的引用(实际上1-值参考),然后返回static_cast<T&&>(t)std::move实际上由于参照塌缩将返回-1-参考值或R值的参考,所以它会表现得更像std::forward不移动.那么什么是诀窍,让它运作正常,我不明白?

c++ move c++11 c++14

0
推荐指数
1
解决办法
503
查看次数