小编use*_*759的帖子

内联函数 - 它们与内联关键字完全相同的是什么?

此链接中,什么是内联函数以及什么是内联关键字.我正在阅读它,因为我意识到我从未理解这两个概念的含义以及它们应该如何在实践中使用.我在引用和评论我提供的链接

内联函数或内联变量(自C++ 17开始)是具有以下属性的函数或变量(自C++ 17起):

1)只要每个定义出现在不同的翻译单元中,程序中的内联函数或变量(自C++ 17)可能有多个定义.例如,内联函数或内联变量(自C++ 17)可以在包含在多个源文件中的头文件中定义.

在这里我已经有了解问题,声明是新标识符的规范

void func(void);
Run Code Online (Sandbox Code Playgroud)

而定义是实际的实现,包括正文

void func(void) {
  //some code...
}
Run Code Online (Sandbox Code Playgroud)

第1点意味着我可以提供不同的实现,只要它们处于不同的翻译单元(即每个源文件的每个头文件一个实现),但我很困惑,因为我有一个source.cc带有声明的源文件func并且一个带有func翻译单元的另一个声明的头文件就是这对,source.cc+header.h并且在这种情况下声明了两次func没有任何意义,是吗?

2)内联函数或变量的定义(因为C++ 17)必须存在于访问它的转换单元中(不一定在访问点之前).

这是通常的情况,我将定义与声明分开,第一个在头文件中,第二个在源文件中,如果我需要使用函数我必须只包含头?接入点将在链接阶段由源提供,是否正确?

3)具有外部链接(例如,未声明为静态)的内联函数或变量(因为C++ 17)具有以下附加属性:1)必须在每个翻译单元中内联声明.2)每个翻译单元都有相同的地址.

你能提供一个简单的例子吗?我无法想象这种情况的实际案例.情况3)声明关键字inline是强制性的,除非要声明的函数是静态的.

我到目前为止所说的一切是否正确?

实际上,当这样的函数非常小时,函数应该是内联的,但并不总是编译器会内联声明为内联的函数,例如,如果它有内部循环或递归(有效C++状态如此).一般来说它依赖于编译器,我现在很奇怪......

假设我有两个函数,第一个是自包含的(它不会在内部调用任何其他函数),第二个调用是第一个(为了参数,你可以假设它们都是10行).它们都应该内联声明吗?它们应该在头文件中声明吗?或者我应该在头文件中分离定义和源文件中的实现?什么会更好?

编辑1:

如果我通过示例工作,并通过相关的汇编代码分析,其中一个答案会更好.

我删除了以前的代码,因为它没有意义(-O3没有设置标志优化).

我重新开始...我有5个文件header.h,src.cc,src1.cc,src2.ccmain.cc.对于每个翻译单元,发布相关的汇编代码.

我以三种不同的方式操作这些文件,然后观察生成的汇编代码,这有助于我理解内联关键字的工作原理.

例1:

header.h

#ifndef HEADER_H_
#define HEADER_H_

int func(int a, int b);
int test_1();
int test_2();

#endif /* HEADER_H_ */
Run Code Online (Sandbox Code Playgroud)

src.cc

#include …
Run Code Online (Sandbox Code Playgroud)

c++ inline function

36
推荐指数
3
解决办法
2149
查看次数

void*作为C中的泛型,是否安全?

准备好一个有点"扭曲"的问题......

我在过去实现了很多数据结构(树,列表,哈希表,图表),使用宏我可以实现某种通用.然而,如果有可能使用void指针实现通用数据结构,我会徘徊,但不知何故,我希望能够使用类型搜索...

我不知道我想说的是否清楚...但基本上我认为将"void*"作为通用并不总是安全的,同时我不认为总是使用宏作为制作通用数据结构的一个好主意(因为基本上预处理器对宏所做的是代码替换),因为如果你环顾网络就可以找到这样的例子.

在我看来,一个好主意可能是,但可能我不对,就是使用宏来为存储在数据结构中的数据建立一个标准接口,在接口函数中我会把代码用于正确的类型检查,给出无效*.受软件工程师techinique的启发,这可能是一个很好的方法.

对于转换语言(C++/Java)来说,可能过于软化的东西肯定是更好的,但事实并非总是如此.

总结一下...... C中的"泛型"问题通常是如何处理的?我依靠你的经验来回答!

c generics

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

std :: set,lower_bound和upper_bound如何工作?

我有这么简单的代码:

#include <iostream>
#include <set>

using std::set;

int main(int argc, char argv) {
   set<int> myset;
   set<int>::iterator it_l, it_u;
   myset.insert(10);
   it_l = myset.lower_bound(11);
   it_u = myset.upper_bound(9);

   std::cout << *it_l << " " << *it_u << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这将打印1作为11的下限,10作为9的上限.

我不明白为什么打印1.我希望使用这两种方法来获得给定上限/下限的一系列值.

c++ containers set

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

-O3 与 -Ofast 优化之间的 gcc 差异

我只是通读 gcc 手册以找出-O3和之间的区别-Ofast

为了 -O3

-O3

Optimize yet more. -O3 turns on all optimizations specified by -O2 and also turns on the following optimization flags:

-fgcse-after-reload 
-fipa-cp-clone
-floop-interchange 
-floop-unroll-and-jam 
-fpeel-loops 
-fpredictive-commoning 
-fsplit-paths 
-ftree-loop-distribute-patterns 
-ftree-loop-distribution 
-ftree-loop-vectorize 
-ftree-partial-pre 
-ftree-slp-vectorize 
-funswitch-loops 
-fvect-cost-model 
-fversion-loops-for-strides
Run Code Online (Sandbox Code Playgroud)

虽然 -Ofast

-Ofast

Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for
all standard-compliant programs. It turns on -ffast-math,
-fallow-store-data-races and the Fortran-specific -fstack-arrays, unless -fmax-stack-var-size is …
Run Code Online (Sandbox Code Playgroud)

gcc compilation compiler-optimization

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

C++使用一种方法实现不同类型的赋值并且没有警告的优雅方式?

我必须实现基本相同的功能,但不同的大小.具体来说就是......

type& operator=(unsigned int);
type& operator=(unsigned long int);
type& operator=(unsigned long long int);
type& operator=(int);
type& operator=(long int);
type& operator=(long long int);
type& operator=(short int);
//so on and so forth...
Run Code Online (Sandbox Code Playgroud)

他们必须做同样的事情...(除了我应该考虑到不同的大小),主要的想法是"如果类型是最广泛使用任务的代码...否则执行转换和执行代码".是否可以通过仅使用一种方法来避免所有这样的重复代码?(我只是不希望编译器在编译时给我一些警告......).

谢谢

c++ polymorphism assignment-operator

5
推荐指数
2
解决办法
174
查看次数

元编程用于优化存储/运行时算法,C++

我想在不考虑底层结构是数组的情况下概括C++中的按位运算符.

例如......如果我想代表86位,我将使用结构结构/类,如:

typedef struct {
 uint64_t x[1];
 uint16_t y[1];
 uint8_t z[1];
} sampleStruct;
Run Code Online (Sandbox Code Playgroud)

相反,如果我想分配160位,我会使用如下结构:

typedef struct {
 uint64_t x[2];
 uint32_t y[1];
} sampleStruct;
Run Code Online (Sandbox Code Playgroud)

我认为存储的一个微不足道但不是最优的解决方案是假设所有块都是统一的并且分配最小值,它覆盖我正在实现的大小,但是即使是练习,我更喜欢我暴露的方式.

对我而言,听起来我应该使用元编程来解决问题,所以我必须正确定义

template <int I>
typedef sampleStruct {
  //something
}
Run Code Online (Sandbox Code Playgroud)

但是我不是C++模板元编程的大专家,所以我想了解实现不同类型的示例struct变量的最佳方法.我知道如何为我的长度决定最好的"封面"是这样的:

N64 = I/64;
RemN = I%64;
if(0 < RemN <= 8) {
  add uint8_t var;
} else if (8 < RemN <= 16) {
  add uint16_t var;
} else if (16 < RemN <= 24) {
  add uint16_t var;
  add uint8_t var;
} else {
  //Similarly …
Run Code Online (Sandbox Code Playgroud)

c++ templates metaprogramming c++11

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

为动态数据结构预分配内存

我有一个问题/好奇心。假设我想实现一个列表,例如我基本上可以使用 cormen book 方法。其中解释了如何实现、插入、删除、键搜索等。

然而,关于内存使用的内容没有说。例如,如果我想在整数列表中插入一个整数。例如,我可以先创建一个节点(我在那里分配内存)插入整数,然后在列表中插入节点。如果我想删除一个整数,一旦我知道存储在哪个节点中,我就必须释放内存。

我现在想知道是否预先分配内存来存储,比如 10 个节点并保留一个指向要使用的空闲节点的指针会更方便。如果内存池已满,那么我会为 20 个节点重新分配内存,如果池很大,则是此类池大小的一半(依此类推)。池的管理当然更复杂,因为我需要例如处理可能的内存碎片等。

我说的有道理吗?还是没有意义?我在一本书中读到,对于游戏编程,内存预分配可以提高性能,但我想知道如何。

c c++ memory memory-management

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

如何分配类中的静态成员?

如果我有类似的课程

class MyClass {
   public:
      int myMember1;
      int myMember2;
      int myMember3;
};
Run Code Online (Sandbox Code Playgroud)

每次我实例化一个MyClass连续三个空间的对象int被分配,那么当我有类似的东西时

class MyClass {
   public:
      static int myMember1;
      int myMember2;
      int myMember3;
};
Run Code Online (Sandbox Code Playgroud)

这次如何分配内存?

我问,因为当我声明同一个类的多个实例时,我不完全确定如何分配内存,是否有指向静态成员的指针?

c++ variables static

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

如何获取 std::set 中给定下限和上限的映射中的一系列值?

假设我有以下代码

#include <iostream>
#include <set>

int main ()
{
  std::set<int> myset;
  int inf, sup;

  inf = 25; sup = 60;
  for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90

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

我试图弄清楚标准库是否提供了任何方法或方法组合,可以让我获得两个迭代器,it_l, it_u从而覆盖范围 [inf,sup]。我尝试过使用 lower_bound、upper_bound 但我误解了它们的工作原理。这个想法是避免编写循环(因为我知道我可以为此任务编写自己的函数,但也许有一些我不知道的替代方案)。

更新:预期输出的一些示例是(在我的示例中)

inf =25; sup = 60我预计{30,40,50,60}

如果相反

inf=30; sup = 60我预计{30,40,50,60}

如果

inf=25; sup = 65我预计{30,40,50,60}

显然这是一个误解,或者也许是我没有正确表达我想做的事情。

当我说 inf 和sup 时,请将它们视为实区间的极值。一旦做出这样的假设,我想要检索的是区间 [inf,sup] 和由集合对象指定的离散集合之间的交集。我刚才说的和我举的例子是不是有些矛盾?

A={10 20 30 40 …

c++ containers std set

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

为Unity构建C++插件

试图创建我的第一个插件.cpp代码是:

标题:

#pragma once
#ifndef __MY_DLL_H
#define __MY_DLL_H

extern "C" int add_1(int number);

#endif
Run Code Online (Sandbox Code Playgroud)

资源:

//FirstDLL.cpp
#include "FirstDLL.h"

extern "C" int add_1(int number) {
    return number + 1;
}
Run Code Online (Sandbox Code Playgroud)

然后我编译并将DLL放在Assets/Plugins文件夹中,dll文件是FirstDLL.dll.从统一方面来说,我有一个简单的C#脚本用于组件:

using UnityEngine;

public class MyBehaviour : MonoBehaviour {

    // Use this for initialization
    [Header("Nuts!")]
    public int my_curr_val;
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        print(add_1(my_curr_val));
    }

    [DllImport("FirstDLL")]
    public static extern int add_1(int number);
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试运行脚本时,我收到以下错误:

插件:无法加载'Assets/Plugins/FirstDLL.dll'并显示错误'此操作仅在应用程序容器的上下文中有效.".插件:无法加载'Assets/Plugins/FirstDLL.dll'并显示错误'此操作仅在应用程序容器的上下文中有效.".DllNotFoundException:FirstDLL MyBehaviour.Update()(在Assets/MyBehaviour.cs:17) …

c# c++ dll unity-game-engine

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