小编Car*_*ton的帖子

订购if ... else if语句的概率是什么?

具体来说,如果我有一系列if... else if语句,并且我事先知道每个语句将评估的相对概率,true它按照概率的顺序对它们进行排序有多大差异?例如,我应该更喜欢这个:

if (highly_likely)
  //do something
else if (somewhat_likely)
  //do something
else if (unlikely)
  //do something
Run Code Online (Sandbox Code Playgroud)

对此?:

if (unlikely)
  //do something
else if (somewhat_likely)
  //do something
else if (highly_likely)
  //do something
Run Code Online (Sandbox Code Playgroud)

很明显,排序版本会更快,但是为了便于阅读或存在副作用,我们可能希望对它们进行非最佳排序.在您实际运行代码之前,很难判断CPU在分支预测方面的表现如何.

因此,在尝试这个过程中,我最终回答了我自己的问题,但我还想听听其他意见/见解.

重要提示:此问题假定if语句可以任意重新排序,而不会对程序的行为产生任何其他影响.在我的回答中,三个条件测试是互斥的,不会产生副作用.当然,如果必须按某种顺序评估陈述以达到某些预期的行为,那么效率问题就没有实际意义.

c++ optimization performance if-statement branch-prediction

184
推荐指数
8
解决办法
1万
查看次数

如何从私有基类调用静态方法?

由于第三方库的布局,我有类似下面的代码:

struct Base
{
    static void SomeStaticMethod(){}
};

struct Derived1: private Base {};

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        Base::SomeStaticMethod();
    }
};

int main() {
    Derived2 d2;
    d2.SomeInstanceMethod();

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

我正在使用MSVC获得编译器错误C2247:

Base :: SomeStaticMethod无法访问,因为Derived1使用private从Base继承.

我知道我不能访问Base从成员Derived2通过继承,因为私人符,但我仍然应该能够调用静态方法Base-无论之间的继承关系BaseDerived2.
如何解决歧义并告诉编译器我只是调用静态方法?

c++ static-methods private-inheritance

25
推荐指数
4
解决办法
2089
查看次数

试图从Derived*的向量中分配Base*的向量

这似乎是一个非常基本的问题,但我无法弄清楚.我有一个std::vectorDerived对象的原始指针,我只想使用赋值运算符将它复制到另一个Base指针向量.使用VC++我得到错误C2679"binary'=':没有找到操作符......"顺便说一下,我不想要对象的深层副本,我只是想复制指针.示例代码:

#include <vector>
using namespace std;

struct Base{};    
struct Derived: public Base {};

int main (int argc, char* argv[])
{
    vector<Derived*> V1;
    vector<Base*> V2;
    V2 = V1;  //Compiler error here
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

让我感到困惑的是,我可以通过循环遍历它来复制矢量并使用push_back,如下所示:

for (Derived* p_derived : V1)
    V2.push_back(p_derived);
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,为什么作业失败,而push_back有效?对我来说似乎是一样的东西.

c++ inheritance pointers vector

13
推荐指数
2
解决办法
1186
查看次数

当你对检索到的值的表达式进行分支时,是否存在像`if(Value*value = getValue())`这样的习惯用法?

我经常使用普通的

if (Value * value = getValue())
{
    // do something with value
}
else
{
    // handle lack of value
}
Run Code Online (Sandbox Code Playgroud)

现在,我也经常这样做

QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty())
{
     // handle the error
}
// empty error means: no error
Run Code Online (Sandbox Code Playgroud)

这一切都很好,但我希望error变量的范围是if-block.那有一个很好的习语吗?显然,我可以将整个部分包装在另一个块中.

显然,这不起作用:

if(QString error = someFunctionReturningAnErrorString(arg), !error.isEmpty())
{
    // handle the error
}
// empty error means: no error
Run Code Online (Sandbox Code Playgroud)

不幸的是(但有充分的理由)QString无法转换为bool,所以这也不起作用:

if(QString error = someFunctionReturningAnErrorString(arg))
{
    // handle the error
}
// empty error …
Run Code Online (Sandbox Code Playgroud)

c++ qstring qt

13
推荐指数
2
解决办法
549
查看次数

派生类模板中的条件覆盖

我有一个Container保存的对象,其类型可以从一些基类的任何组合衍生的(类TypeA,TypeB等).基类Container具有返回指向包含对象的指针的虚方法; nullptr如果包含的对象不是从期望的类派生的,那么它们应该返回.我想根据Container模板参数有选择地覆盖base的方法.我尝试使用SFINAE如下,但它不编译.我想避免专注Container于所有可能的组合,因为可能有很多.

#include <type_traits>
#include <iostream>

using namespace std;

class TypeA {};
class TypeB {};
class TypeAB: public TypeA, public TypeB {};

struct Container_base {
    virtual TypeA* get_TypeA() {return nullptr;}
    virtual TypeB* get_TypeB() {return nullptr;}
};

template <typename T>
struct Container: public Container_base
{
    Container(): ptr(new T()) {}

    //Override only if T is derived from TypeA
    auto get_TypeA() -> enable_if<is_base_of<TypeA, T>::value, TypeA*>::type
    {return ptr;}

    //Override only if …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance templates sfinae c++11

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

如何一次将几个unique_ptrs插入到vector中

我有一个矢量:

std::vector<std::unique_ptr<int>>
Run Code Online (Sandbox Code Playgroud)

并希望unique_ptr<int>在指定位置插入几个新的.有成员函数,std::vector::insert(iterator position, size_type n, const value_type& val)但唉,复制的限制unique_ptr不允许使用这个重载.

我已经读过这个问题,但是那个插入unique_ptr已存在于另一个向量中的问题.我想创造新的.

我意识到我可以用循环来做,例如在向量的开头插入3个新项:

for (int n = 0; n != 3; ++n)
   vec.insert(vec.begin(), std::make_unique<int>(0));
Run Code Online (Sandbox Code Playgroud)

但是我想知道是否有更简洁的方法来做到这一点,并且可能是一个预先分配新内存的方法.

编辑澄清:添加到向量的项目数是完全随意的 - 我在我的示例代码中写了3但它可以是任何值,而不一定是编译时已知的值.

c++ vector unique-ptr

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

插入从函数返回的std :: vector

我发现自己经常做这样的事情来连接从函数返回的几个向量(可能是类函数):

#include <vector>
#include <iostream>
using namespace std;

vector<int> v1;

const vector<int>& F1() {
    cout << "F1 was called" << endl;
    /*Populate v1, which may be an expensive operation*/
    return v1;
}

int main() {
    vector<int> Concat;
    Concat.insert(Concat.end(), F1().begin(), F1().end());
    /*Do something with Concat*/
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如我所料,F1()被调用两次,如果它是一个昂贵的函数调用,这可能是不可取的.另一种方法是将返回值复制F1()到一个临时向量中,该向量只需要一个函数调用,但是如果向量很大则会产生复制操作,这可能是不合需要的.我能想到的唯一另一种选择是创建一个指向临时向量的指针,并为其分配返回值,F1()如下所示:

int main() {
    vector<int> Concat;
    const vector<int>* temp = &F1();
    Concat.insert(Concat.end(), temp->begin(), temp->end());
    /*Do something with Concat*/
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这真的是最好的解决方案吗?使用临时变量似乎很麻烦,特别是如果我需要连接几个向量.我也觉得应该有一种方法来使用引用而不是指针来做到这一点.有什么建议?

c++ vector

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

删除行时QModelIndex变为无效

我在子类QAbstractItemModel中显示a中的项目QTreeView,在这个子类(projectModel)中,我有一个函数来删除树视图中当前选择的索引. Component是用于表示模型的所有成员的类:

void
projectModel::deleteComponent()
{
    QModelIndex child_index = _treeview->selectionModel()->currentIndex();
    Component* child = static_cast<Component*>(child_index.internalPointer());

    Component* parent = child->Parent();
    QModelIndex parent_index = createIndex(parent->row(), 0, parent);

    int row = child->row();

    beginRemoveRows(parent_index, row, row);
    parent->delete_child(child);
    endRemoveRows();
}
Run Code Online (Sandbox Code Playgroud)

在呼叫之前,父母和孩子的指示和原始指针都很好beginRemoveRows; 调试器显示它们指向正确的项目及其父项.但是,程序在调用后崩溃了beginRemoveRows.具体来说,它崩溃了 projectModel::parent():

QModelIndex
projectModel::parent(const QModelIndex &index) const
{    
    if (!index.isValid())
        return QModelIndex();

    Component* item = getItem(index);        //Fails to cast index internal pointer to a valid Component*
    Component* parentItem = item->Parent();

    if (parentItem == _rootnode) …
Run Code Online (Sandbox Code Playgroud)

c++ qt qabstractitemmodel

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

如何使用一行代码连接两个向量

我发誓这不是任何看似无限数量的矢量连接线程的重复.对于我的情况,在派生类构造函数中,我需要将a传递std::vector<int>给基类构造函数,但传递的向量需要是另外两个向量的串联.例:

#include <vector>    
using namespace std;

struct Base {
    Base(vector<int> numbers) {
        //Do something with numbers
    }
};

struct Derived: public Base {
    Derived(vector<int> numbers):
        Base(concatenate(numbers, {4,5,6})) {}  //Is there a built-in "concatenate" function?
}; 

int main (int argc, char* argv[])
{
    Derived D({1,2,3});
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我显然可以通过编写自己的concatenate函数来实现这一点,但我想知道是否已经有了标准库方法来实现这一点.我发现的矢量级联的例子都不适合在初始化列表中使用,因为它们跨越多行; 我需要一个单线串联.

c++ stdvector

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

在函数返回值中定义新类型

我惊讶地发现以下代码在MSVC下编译,运行和生成预期输出:

#include <iostream>
using namespace std;

struct Foo{
    int _x;
    Foo(int x): _x(x) {}
}  //Note: no semi-colon after class definition.
   //Makes this behave as a return type for the following function:

Foo_factory(int x)
{return Foo(x);}

int main (int argc, char* argv[])
{
    Foo foo = Foo_factory(42);
    cout << foo._x << endl;  //Prints "42"
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我没有惊讶地看到MinGW无法编译错误"可能没有在返回类型中定义新类型".这只是该标准的另一个Microsoft例外,还是这个合法的C++?

c++ visual-c++

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

复制省略并移动语义不按预期工作

我做了一个程序来评估这样做之间的性能差异:

func3(func2(func1()));
Run Code Online (Sandbox Code Playgroud)

对此:

retval1 = func1();
retval2 = func2(retval1);
func3(retval2);
Run Code Online (Sandbox Code Playgroud)

我更喜欢后者的可读性和易于调试,我想知道编译器(MSVC 12.0)是否会优化发布版本中的中间对象.我的测试程序是这样的:

#include <iostream>

using namespace std;

struct Indicator {
    Indicator() {cout << "Default constructor" << endl;}
    Indicator(const Indicator& other) {cout << "Copy constructor" << endl;}
    const Indicator& operator=(const Indicator& other) {cout << "Assignment operator" << endl;}
    ~Indicator() {cout << "Destructor" << endl;}
};

Indicator func1()
{return Indicator();}

Indicator func2(Indicator&& i)
{return std::move(i);}

Indicator func3(Indicator&& i)
{return std::move(i);}

int main() {
    Indicator i = func3(func2(func1()));
    cout << &i << endl; …
Run Code Online (Sandbox Code Playgroud)

c++ optimization

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