假设我有一些类层次结构,其中有几个virtual函数返回容器引用:
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
class Interface {
public:
virtual const std::vector<int>& getArray() const = 0;
virtual const std::set<int>& getSet() const = 0;
virtual const std::map<int, int>& getMap() const = 0;
};
class SubclassA : public Interface {
public:
const std::vector<int>& getArray() const override { return _vector; }
const std::set<int>& getSet() const override { return _set; }
const std::map<int, int>& getMap() const override { return _map; }
private:
std::vector<int> _vector;
std::set<int> _set; …Run Code Online (Sandbox Code Playgroud) 我想写一个函数:
现在,如果我想要 1+2,我就会使用gsl::span. 如果想要 1+3 我会使用owner<T*>. 但当我想要这三个时我该怎么办?我应该通过吗owner<gsl::span<T>>?还有别的事吗?
笔记:
std::vector要求太多。该函数不应该要求调用者构造一个std::vector.我有一个带有std :: vector <int>成员的类和一个返回对该向量的const引用的成员函数.
class demo {
public:
//...
const std::vector<int> & test() const {
return iv;
}
private:
std::vector<int> iv;
};
Run Code Online (Sandbox Code Playgroud)
我计划将成员类型更改为不同的数组,如容器类型,具有足够的功能和更小的内存占用(例如std :: experimental :: dynarray,std :: unique_ptr <int []>).因此,我认为不将真实容器作为const引用返回,而是将视图作为gsl :: span <const int>返回给元素是个好主意.
class demo {
public:
//...
gsl::span<const int> test() const {
return iv;
}
private:
std::vector<int> iv;
};
Run Code Online (Sandbox Code Playgroud)
但这会破坏使用const vector <int>的代码,因为同一个未修改的向量的两个span实例不能用于迭代元素:
demo d;
std::cout << (d.test().begin() == d.test().begin()) << "\n";
std::cout << (d.test().end() == d.test().end()) << "\n";
for( auto it = d.test().begin(), end = d.test().end(); it …Run Code Online (Sandbox Code Playgroud) 在阅读Microsoft's implementation of Cpp Core Guidelines 时,我遇到了两个问题:
gsl::string_span在gsl::span已经运行良好的地方提供?gsl::zstring_span在std::string自 C++11 以来已保证以空值终止的地方提供?任何说明情况都将受到高度赞赏。
我们正在工作中尝试std::span()(目前使用 gsl 实现)。最近我们发现将 astd::span.size()与 a进行比较vector.size()会得到 a -Wsign-compare error:
if( span.size() > vector.size() ) // comparison between signed and unsigned integer expressions [-Wsign-compare]
Run Code Online (Sandbox Code Playgroud)
我认为我们不想对每一项比较都进行选角。我们的编码指南将这些警告视为错误。好奇是否有人有任何想法或建议?
我目前尝试使用生成器将Visual Studio 2017 的C ++核心准则检查器(CppCoreCheck)与元生成系统CMake集成在一起Visual Studio 15 2017 Win64。
以下示例说明了我的方法(我尝试将CMake源代码精简到最小)。
首先,我将所有编译器开关添加到了构建目标,以使用CppCoreCheck进行分析:
cmake_minimum_required(VERSION 3.12)
project(cppcorecheck-example)
find_package(Boost REQUIRED MODULE)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE Boost::boost)
target_compile_options(app
PRIVATE
"/analyze"
"/analyze:WX-"
"/analyze:log" "cppcorecheck.xml"
"/analyze:stacksize" 16384
"/analyze:max_paths" 256
"/analyze:ruleset" "CppCoreCheckRules.ruleset"
"/analyze:plugin EspXEngine.dll"
)
Run Code Online (Sandbox Code Playgroud)
我正在使用以下内容main.cpp:
#include <boost/system/error_code.hpp>
int main() {
int arr[10]; // warning C26494
int* p = arr; // warning C26485
{
int* q = p + 1; // warning C26481
p = q++; // warning C26481
} …Run Code Online (Sandbox Code Playgroud) c++ cmake visual-studio static-code-analysis cpp-core-guidelines
msvc 的 cpp 核心指南代码分析器告诉我
警告 C26472 不要使用 a
static_cast进行算术转换。使用大括号初始化,gsl::narrow_cast或gsl::narrow(type.1)。
对于这个片段
static_cast<IntType>(static_cast<unsigned long long>(hexValue(digit)) << (digitIdx * 4));
Run Code Online (Sandbox Code Playgroud)
为什么我不应该在这里使用 static_cast ?
另外,使用大括号初始化,这看起来像这样
IntType{unsigned long long{hexValue(digit)} << (digitIdx * 4)};
Run Code Online (Sandbox Code Playgroud)
我认为这看起来并没有更好。这看起来更像是函数风格的转换而不是其他任何东西。
我无法使用 gsl 并且我认为gsl::narrow它是自身的包装器static_cast,所以这纯粹是一个可读性问题吗?
当我使用以下代码时,我收到一条警告(来自应用 cppcoreguideline)。代码:
SampleClass *object = nullptr;
object = new SampleClass();
Run Code Online (Sandbox Code Playgroud)
警告:
warning: assigning newly created 'gsl::owner<>' to non-owner 'SampleClass *' [cppcoreguidelines-owning-memory]
Run Code Online (Sandbox Code Playgroud)
我无法理解,有人可以用简单的术语解释一下。
我最近正在阅读这篇文章,其中指出:
不要认为复杂的代码一定比简单的代码快。
代码复制如下:
例子,不错
// clear expression of intent, fast execution
vector<uint8_t> v(100000);
for (auto& c : v)
c = ~c;
Run Code Online (Sandbox Code Playgroud)
例子,坏
// intended to be faster, but is often slower
vector<uint8_t> v(100000);
for (size_t i = 0; i < v.size(); i += sizeof(uint64_t)) {
uint64_t& quad_word = *reinterpret_cast<uint64_t*>(&v[i]);
quad_word = ~quad_word;
}
Run Code Online (Sandbox Code Playgroud)
我不确定坏例子的目的是什么,为什么它打算更快?
为什么它实际上通常更慢?
C++ 核心指南建议dynamic_cast在“类层次结构导航不可避免”时使用。这触发铛,整洁抛出以下错误:Do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]。
指导方针继续说:
注意:
像其他演员一样,
dynamic_cast被过度使用。更喜欢virtual函数而不是铸造。在可能的情况下(不需要运行时解析)并且相当方便,更喜欢静态多态性而不是层次结构导航。
我一直只使用嵌套在我的基类中的enum命名Kind,并static_cast根据其类型执行 a 。阅读 C++ 核心指南,“...即便如此,根据我们的经验,诸如“我知道我在做什么”的情况仍然是一个已知的错误来源。” 建议我不应该这样做。通常,我没有任何virtual函数,所以 RTTI 不存在使用dynamic_cast(例如,我会得到error: 'Base_discr' is not polymorphic)。我总是可以添加一个virtual函数,但这听起来很傻。该指南还说在考虑使用我使用的判别方法之前先进行基准测试Kind。
enum class Kind : unsigned char {
A,
B,
};
class Base_virt {
public:
Base_virt(Kind p_kind) noexcept : m_kind{p_kind}, m_x{} …Run Code Online (Sandbox Code Playgroud) c++ polymorphism dynamic-cast static-polymorphism cpp-core-guidelines
c++ ×10
c++11 ×2
array-view ×1
c++14 ×1
cmake ×1
dynamic-cast ×1
performance ×1
polymorphism ×1