// g++ --std=c++17 test.cpp -I /usr/local/include -L /usr/local/lib -lboost_system -Wall -pedantic -Wreturn-type -Wstrict-aliasing -Wreturn-local-addr -fsanitize=address -g
// LD_LIBRARY_PATH=/usr/local/lib ./a.out
#include <iostream>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
class A {
public:
fs::path path_;
const fs::path & path() const { return path_; }
fs::path & path() { return path_; }
};
class B {
public:
fs::path root_path_;
A path_2;
A path_3;
const fs::path & operator()() const {
for (const auto & path : {
path_3.path(),
path_2.path(),
root_path_
}) {
if (not path.empty()) {
return path;
}
}
throw std::logic_error{"using default-constructed B"};
}
};
int main(int argc, char **argv) {
B b;
b.root_path_ = "foo/";
b.path_2.path() = "foo/bar";
b.path_3.path() = "foo/baz";
std::cout << b() << '\n';
return 0;
}
上記のコードは、私が知っている限り、有効なC++と思われます。代わりに、呼び出されるとガベージ出力が表示されます。変数のループのためのrangedは、ローカル変数のアドレス参照を返しますか?
g++
は、最初に文句を言いませんが、アドレスサニタイザーはになります。 -O2
を追加すると、最終的にg++
が文句を言う。私が代わりにポインタを使用してエラーを解決
$ cat /etc/fedora-release
Fedora release 25 (Twenty Five)
$ g++ --version
g++ (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
注:生成された警告は、私が使用しています
test.cpp: In member function ‘const boost::filesystem::path& B::operator()() const’:
test.cpp:31:12: warning: function may return address of local variable [-Wreturn-local-addr]
return path;
^~~~
test.cpp:29:3: note: declared here
}) {
^
注意です。
const fs::path & operator()() const {
for (const auto * path : {
&path_3.path(),
&path_2.path(),
&root_path_
}) {
if (not path->empty()) {
return *path;
}
}
throw std::logic_error{"using default-constructed B"};
}
しかし、私の心の中でいくつかの質問を残す行います-O2
が追加されるまで
- なぜ
g++
ない問題について文句を言うのでしょうか? - 私のコードは正確には何のために定義されていませんか?私はそれがよく定義されていると言うでしょう:
B::operator() const
は...まあ... const。つまり、のオブジェクトがローカルまたはconstメンバーのいずれかであることを意味します。 constメンバーにアクセスします。それはローカル変数const auto &
を構築します。... constメンバーフィールドを参照する必要があります。まさにそれが一時的にバインドされる原因は何ですか?
参照が最初に返されるのはなぜですか? – chris
この例はスリム化されています。セレクタ関数として 'operator()'を使って、他の関数への入力としてどのメンバ変数を使うかを決めています。なぜ私はそれを変更する必要がない非const(または非const参照)を返しますか? – inetknght
'const'値で返すのは一般的な欠点です。まず、呼び出し側の戻り値は分離されているため、関数が変更を行うかどうかは関係ありません。第二に、RVOを阻害する。とにかく、あなたが実際のコードでイニシャライザーリストを使用している場合、言語が最終的に移動できるように変更されない限り、コピーが必要なので、それはうまく終了しません。 – chris